sql >> Base de Datos >  >> RDS >> PostgreSQL

aparente violación de aislamiento de transacciones en postgresql

Sí y No, como siempre, depende. La documentación estrictamente dice que:

En otras palabras, simplemente SELECCIONAR difiere de SELECCIONAR PARA ACTUALIZAR/ELIMINAR/ACTUALIZAR.

Puede crear un caso de prueba simple para observar ese comportamiento:

Sesión 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=>

Ahora inicie sesión en otra Sesión 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;

Después del último comando SELECT ... FOR UPDATE la sesión 1 se "cuelga" y está esperando algo ......

Volver a la sesión 1

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

Y ahora, cuando regrese a la sesión 2, verá esto:

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)

Es decir - simple SELECT todavía no ve ningún cambio, mientras que SELECT ... FOR UPDATE ve que las filas han sido eliminadas. Pero no ve nuevas filas insertadas por la sesión 1

De hecho, una secuencia que está viendo es:

  • el proceso A inicia su transacción
  • el proceso A elimina todo de la tabla T
  • el proceso B inicia su transacción
  • el proceso B intenta seleccionar para actualizar una fila en la tabla T
  • el proceso B "se bloquea" y está esperando hasta que la sesión A realice una confirmación o reversión
  • el proceso A vuelve a llenar la tabla T a partir de los datos entrantes
  • el proceso A confirma su transacción
  • el proceso B aparece vacío (0 filas, después de la confirmación de la sesión A) y llama a revertir