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.
-
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
-
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
-
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 ?