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

violation apparente de l'isolation des transactions dans postgresql

Oui et non - comme d'habitude, ça dépend. La documentation dit strictement que :

En d'autres termes, SELECT diffère simplement de SELECT FOR UPDATE/DELETE/UPDATE.

Vous pouvez créer un scénario de test simple pour observer ce comportement :

Session 1

test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
 x
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
(10 rows)


test=> DELETE FROM test;
DELETE 10
test=>

Connectez-vous maintenant à une autre Session 2 :

test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
 x
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
(10 rows)


test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;

Après la dernière commande SELECT ... FOR UPDATE la session 1 "se bloque" et attend quelque chose ......

Retour à la session 1

test=> insert into test select * from generate_series(1,10);
INSERT 0 10
test=> commit;
COMMIT

Et maintenant, lorsque vous reviendrez à la session 2, vous verrez ceci :

test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
 x
---
(0 rows)


test=> select * from test;
 x
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
(10 rows)

C'est - simple SELECT ne voit toujours aucun changement, tandis que SELECT ... FOR UPDATE voit que des lignes ont été supprimées. Mais il ne voit pas les nouvelles lignes insérées par la session 1

En fait, une séquence que vous voyez est :

  • le processus A démarre sa transaction
  • le processus A supprime tout de la table T
  • le processus B démarre sa transaction
  • le processus B tente une sélection de mise à jour sur une ligne de la table T
  • le processus B "se bloque" et attend que la session A effectue une validation ou une annulation
  • le processus A repeuple la table T à partir des données entrantes
  • le processus A valide sa transaction
  • le processus B est vide (0 lignes - après la validation de la session A) et appelle la restauration