3 votes

PostgreSQL - MVCC (multi-version concurrency control) - Quand le verrou réel est-il acquis ?

D'après ce que j'ai compris, postgres utilise deux champs supplémentaires Xmin et Xmax pour mettre en œuvre mvcc, Disons que nous avons une table Employé avec les colonnes id et name.

Voici quelques opérations grossières et la façon dont elles fonctionnent simultanément (en considérant le niveau d'isolation = READ_COMMITTED). La question est de savoir quand et où le verrou réel est acquis.

  1. Insérer -> Une nouvelle transaction insère un nouvel enregistrement qui n'est pas visible pour les autres transactions jusqu'à ce qu'il soit validé, donc aucun problème dans ce cas et aucun verrouillage ou contrôle de version n'est requis. Disons que id = 1, name = "aa" est inséré. Postgres ajoute 2 colonnes supplémentaires pour mvcc Xmin = id txn actuel (disons 100) et Xmax = 0/null.

    id | name | Xmin | Xmax

    1 | aa | 100 | null

  2. Mise à jour avec lecture simultanée -

    a). Une nouvelle transaction est lancée pour mettre à jour le nom en "bb" (pour id = 1). Au même moment, il y a une autre transaction lancée pour lire les mêmes données.

    b). Un nouveau Tuple (objet immuable dans postgres représentant une ligne) est créé avec Xmin = id de la transaction actuelle (disons 200) et Xmax = null avec id = 1, name = bb. L'ancienne version de id = 1 est également mise à jour pour avoir Xmax = 200. La transaction de lecture voit l'ancienne version des données avec Xmin = 100 et retourne. Un verrouillage est-il nécessaire dans ce cas ? Je pense que non, mais il pourrait être nécessaire de mettre à jour le Xmax de l'ancien tuple.

Ci-dessous, le même enregistrement avec plusieurs versions (juste à titre d'explication), la dernière version ayant Xmax = null.

id  |   name | Xmin | Xmax
------------------------------
1   |   aa   | 100  | 200
1   |   bb   | 200  | null
  1. Mise à jour avec mise à jour simultanée -

    a). Une transaction (avec txn id = 300) a commencé à mettre à jour id = 1 en nom = cc. Une autre transaction (txn id = 400) a commencé à mettre à jour le même enregistrement (id = 1) avec le nom = dd. Si ce scénario se déroule de la même manière en créant un nouveau tuple et en marquant le Xmax de l'ancien tuple, je pense que cela créera des problèmes car 300 et 400 créeront un nouveau tuple et marqueront le Xmax de l'ancien tuple = txn id. Une mise à jour pourrait perdre dans ce cas.

Dans ce scénario, est-ce que le verrou exclusif est acquis par le premier txn et les autres txns de mise à jour concurrents attendent que le txn en cours soit terminé ou est-ce que postgres le gère d'une autre manière ?

4voto

jjanes Points 3442

Insertion -> Une nouvelle transaction insère un nouvel enregistrement qui n'est pas visible pour les autres transactions jusqu'à ce qu'elle soit validée, donc aucun problème dans ce cas et aucun verrouillage ou contrôle de version n'est requis.

Ce n'est pas vrai. Le tuple inséré est verrouillé lors de l'insertion. C'est important si, par exemple, il existe une contrainte unique et que quelqu'un d'autre essaie d'insérer un tuple en conflit.

Mise à jour avec lecture simultanée..... Un verrouillage est-il nécessaire dans ce cas ?

Pendant que le xmax est mis à jour, il y a un verrou "léger" sur le tampon contenant le tuple qui sera libéré dès que le champ sera mis à jour (et non maintenu pendant la durée de la transaction). Ce verrou léger comprend une barrière pour s'assurer que tout autre processus verra la modification effectuée, plutôt que de voir une version en cache périmée de celle-ci.

Le lecteur verra, selon le moment où il est arrivé là, soit que xmax est 0 et retournera le tuple, soit il verra que xmax est 200 et verra que 200 n'est pas encore validé, et retournera quand même le tuple parce qu'il sait que le verrou représenté par xmax = 200 ne s'applique pas à lui, un simple lecteur.

Mise à jour avec mise à jour simultanée...

Le premier processus à inscrire son identifiant dans le xmax du tuple à obsolète gagnera. Le second verra l'identifiant valide de quelqu'un d'autre dans xmax, et bloquera jusqu'à ce que l'autre transaction valide ou annule, puis décidera quoi faire. En raison du verrou léger sur le tampon contenant le tuple, elles ne peuvent pas toutes deux mettre à jour xmax sans remarquer les changements de l'autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X