PostgreSQL viene con características sólidas y probadas que le permiten definir exactamente lo que debería suceder cuando varios clientes intentan actualizar los mismos datos al mismo tiempo. Uno de ellos es el nivel de aislamiento de las transacciones.
Siga leyendo para obtener más información sobre cómo funciona el aislamiento de transacciones en PostgreSQL.
Transacciones y Nivel de Aislamiento
Las transacciones son la forma fundamental de mutar datos en un RDBMS. Los RDBMS modernos permiten que más de una transacción se ejecute simultáneamente y, en consecuencia, vienen con una variedad de herramientas (algunas estándar, otras específicas de RDBMS) para que los desarrolladores de aplicaciones especifiquen cómo sus transacciones deben o no interactuar con otras transacciones.
Los niveles de aislamiento de transacciones y los bloqueos pesimistas son dos de esas herramientas. Aunque estos son necesarios para la integridad y el rendimiento de los datos, lamentablemente no son intuitivos de entender o usar.
El nivel de aislamiento de una transacción, en PostgreSQL, puede ser uno de los siguientes:
- Lectura confirmada
- Lectura repetible
- Serializable
Cada transacción tiene su nivel de aislamiento establecido en uno de estos cuando se crea. El nivel predeterminado es "lectura confirmada".
Tenga en cuenta que el estándar SQL también define "lectura no confirmada", que no es compatible con Postgres. Tienes que usar el nivel más cercano y más alto de "lectura confirmada".
Veamos qué significan estos niveles.
Lectura confirmada
¿Qué sucede cuando una transacción (sin terminar) inserta filas en una tabla y la otra transacción (también sin terminar) intenta leer todas las filas de la tabla? Si la segunda transacción puede ver las filas insertadas por la primera, esa lectura se denomina lectura sucia. – porque la primera transacción puede retroceder y la segunda transacción habría leído filas "fantasmas" que nunca existieron.
La lectura confirmada el nivel de aislamiento garantiza que las lecturas sucias nunca ocurrirán. Aquí hay un ejemplo:
Como puede ver, la segunda transacción no pudo leer la primera transacción como datos aún no confirmados. En PostgreSQL, no es posible bajar el nivel de aislamiento por debajo de este nivel para permitir lecturas sucias.
Lectura repetible
Otro problema más es el de las lecturas no repetibles. Esto sucede cuando una transacción lee una fila y luego la vuelve a leer un poco más tarde, pero obtiene un resultado diferente, porque otra transacción actualizó la fila en el medio. La lectura se ha vuelto no repetible , como se muestra en este ejemplo:
Para solucionar este problema, establezca el nivel de aislamiento de la transacción en "lectura repetible". PostgreSQL luego se asegurará de que la segunda (o cualquier) lectura también devuelva el mismo resultado que la primera lectura. Este es el mismo escenario en el nivel de aislamiento mejorado:
Tenga en cuenta que el nivel de aislamiento se especificó junto con la instrucción BEGIN. También es posible especificar esto a nivel de conexión (como parámetro de conexión), como parámetro de configuración (default_transaction_isolation
) y usando la instrucción SET TRANSACTION.
Serializable
El siguiente nivel de aislamiento aborda el problema de las actualizaciones perdidas . Las actualizaciones realizadas en una transacción pueden "perderse" o sobrescribirse por otra transacción que se ejecute simultáneamente, como se muestra aquí:
Aquí se bloquea la ACTUALIZACIÓN de la segunda transacción, porque PostgreSQL coloca un bloqueo para evitar otra actualización hasta que finalice la primera transacción. Sin embargo, el cambio de la primera transacción se pierde porque la segunda "sobrescribió" la fila.
Si este tipo de comportamiento no es aceptable, puede actualizar el nivel de aislamiento a serializable:
En este nivel, falla la confirmación de la segunda transacción. Las acciones de la segunda transacción se basaron en hechos que se invalidaron cuando estaba a punto de cometerse.
Si bien la serialización brinda el más alto nivel de seguridad, también significa que la aplicación debe detectar dichos errores de confirmación y volver a intentar toda la transacción.