PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Interblocages dans PostgreSQL lors de l'exécution de UPDATE

Dans PostgreSQL, les lignes seront verrouillées au fur et à mesure de leur mise à jour -- en fait, la façon dont cela fonctionne réellement est que chaque tuple (version d'une ligne) a un champ système appelé xmin pour indiquer quelle transaction a rendu ce tuple courant (par insertion ou mise à jour) et un champ système appelé xmax pour indiquer quelle transaction a expiré ce tuple (par mise à jour ou suppression). Lorsque vous accédez aux données, il vérifie chaque tuple pour déterminer s'il est visible pour votre transaction, en vérifiant votre "instantané" actif par rapport à ces valeurs.

Si vous exécutez un UPDATE et qu'un tuple qui correspond à vos conditions de recherche a un xmin qui le rendrait visible pour votre instantané et un xmax d'une transaction active, il se bloque en attendant que cette transaction se termine. Si la transaction qui a mis à jour le tuple en premier est annulée, votre transaction se réveille et traite la ligne ; si la première transaction est validée, votre transaction se réveille et agit en fonction du niveau d'isolement actuel de la transaction.

De toute évidence, un blocage est le résultat de ce qui se passe dans des lignes dans un ordre différent. Il n'y a pas de verrou au niveau des lignes dans la RAM qui peut être obtenu pour toutes les lignes en même temps, mais si les lignes sont mises à jour dans le même ordre, vous ne pouvez pas avoir le verrouillage circulaire. Malheureusement, le IN(1, 2) suggéré la syntaxe ne le garantit pas. Différentes sessions peuvent avoir différents facteurs de coût actifs, une tâche "d'analyse" en arrière-plan peut modifier les statistiques de la table entre la génération d'un plan et l'autre, ou elle peut utiliser un seqscan et être affectée par l'optimisation PostgreSQL qui provoque un nouveau seqscan pour en rejoindre un déjà en cours et "faire une boucle" pour réduire les E/S de disque.

Si vous effectuez les mises à jour une par une dans le même ordre, dans le code de l'application ou à l'aide d'un curseur, vous n'aurez alors qu'un simple blocage, pas des interblocages. En général, cependant, les bases de données relationnelles sont sujettes aux échecs de sérialisation, et il est préférable d'y accéder via un framework qui les reconnaîtra en fonction de SQLSTATE et réessayera automatiquement la transaction entière depuis le début. Dans PostgreSQL, un échec de sérialisation aura toujours un SQLSTATE de 40001 ou 40P01.

http://www.postgresql.org/docs/current/interactive/mvcc-intro.html