Relación de niveles de aislamiento de transacciones con bloqueos en la mesa

105

He leído sobre 4 niveles de aislamiento:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Quiero entender el bloqueo que toma el aislamiento de cada transacción sobre la mesa.

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

A continuación se muestran los tres fenómenos que pueden ocurrir en el aislamiento de transacciones
Lectura sucia - sin bloqueo
Lectura no repetible - sin lectura sucia como bloqueo en datos comprometidos
Lectura fantasma - bloqueo en bloque de sql (que se selecciona mediante la consulta de selección)

Quiero entender dónde definimos estos niveles de aislamiento: solo en el nivel jdbc / hibernate o en DB también

PD: he revisado los enlaces en los niveles de aislamiento en Oracle , pero se ven torpes y hablan sobre bases de datos específicas

Aprendiz
fuente
3
Esto depende completamente de la base de datos. Diferentes bases de datos pueden utilizar diferentes algoritmos para los niveles de aislamiento. Algunos pueden usar MVCC (sin bloqueos en consultas seleccionadas), algunos usan bloqueo estricto de 2 fases (bloqueos compartidos y exclusivos).
Té brb

Respuestas:

157

Quiero entender el bloqueo que toma el aislamiento de cada transacción sobre la mesa.

Por ejemplo, tiene 3 procesos simultáneos A, B y C. A inicia una transacción, escribe datos y confirma / deshace (según los resultados). B simplemente ejecuta una SELECTdeclaración para leer datos. C lee y actualiza datos. Todos estos procesos funcionan en la misma mesa T.

  • LEER SIN COMPROMISO : no hay candado en la mesa. Puede leer los datos de la tabla mientras escribe en ella. Esto significa que A escribe datos (no confirmados) y B puede leer estos datos no confirmados y usarlos (para cualquier propósito). Si A ejecuta una reversión, B todavía ha leído los datos y los ha utilizado. Esta es la forma más rápida pero más insegura de trabajar con datos, ya que puede generar agujeros de datos en tablas no relacionadas físicamente (sí, dos tablas pueden estar relacionadas de forma lógica pero no física en aplicaciones del mundo real = \).
  • LEER COMPROMISO : bloquea los datos confirmados. Puede leer los datos que solo se comprometieron. Esto significa que A escribe datos y B no puede leer los datos guardados por A hasta que A ejecute una confirmación. El problema aquí es que C puede actualizar los datos que se leyeron y usaron en B y el cliente B no tendrá los datos actualizados.
  • LECTURA REPETIBLE : bloquee un bloque de SQL (que se selecciona mediante la consulta de selección). Esto significa que B lee los datos bajo alguna condición WHERE aField > 10 AND aField < 20, es decir , A inserta datos donde el aFieldvalor está entre 10 y 20, luego B lee los datos nuevamente y obtiene un resultado diferente.
  • SERIALIZABLE : bloquear en una tabla completa (en la que se activa la consulta Seleccionar). Esto significa que B lee los datos y ninguna otra transacción puede modificar los datos de la tabla. Esta es la forma más segura pero más lenta de trabajar con datos. Además, dado que una simple operación de lectura bloquea la tabla , esto puede ocasionar serios problemas en la producción: imagine que la tabla T es una tabla de facturas, el usuario X desea conocer las facturas del día y el usuario Y desea crear una nueva factura, por lo que mientras X ejecuta la lectura de las facturas, Y no puede agregar una nueva factura (y cuando se trata de dinero, la gente se enoja mucho, especialmente los jefes).

Quiero entender dónde definimos estos niveles de aislamiento: solo en el nivel JDBC / hibernate o en DB también

Usando JDBC, lo define usando Connection#setTransactionIsolation.

Usando Hibernate:

<property name="hibernate.connection.isolation">2</property>

Dónde

  • 1: LEER SIN COMPROMISO
  • 2: LEER COMPROMETIDO
  • 4: LECTURA REPETIBLE
  • 8: SERIALIZABLE

La configuración de Hibernate se toma de aquí (lo siento, está en español).

Por cierto, también puede establecer el nivel de aislamiento en RDBMS:

y así sucesivamente...

Luiggi Mendoza
fuente
docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Solo para agregar para Oracle: se puede establecer el nivel de aislamiento de una transacción utilizando una de estas declaraciones al comienzo de una transacción: SET TRANSACTION ISOLATION NIVEL LEÍDO COMPROMETIDO; FIJAR NIVEL DE AISLAMIENTO DE TRANSACCIÓN SERIALIZABLE; CONFIGURAR TRANSACCIÓN SOLO LEER;
Estudiante
2
Además, para ahorrar el costo de red y procesamiento de comenzar cada transacción con una instrucción SET TRANSACTION, puede usar la instrucción ALTER SESSION para establecer el nivel de aislamiento de transacciones para todas las transacciones posteriores: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
Estudiante
12
Con respecto a REPEATABLE READ, creo que un mejor ejemplo para demostrarlo es el siguiente: B inicia una transacción, lee datos en el bloque de sql DONDE aField> 10 Y aField <20, esos datos se bloquean hasta que finaliza la transacción. A intenta actualizar esos datos pero espera debido al bloqueo. Ahora, cuando B vuelva a leer esos datos en esa misma transacción, se garantiza que leerá los mismos datos, porque está bloqueado. Corrígeme si me equivoco.
BornToCode
1
@LuiggiMendoza Como concepto general, los niveles de aislamiento son solo lectura sucia , lectura no repetible y filas fantasma . Los bloqueos (S2PL) o MVCC son implementaciones para diferentes proveedores.
Té brb
4
@LuiggiMendoza - No fui exacto, debería ser así: los datos que B leyó no se modifican, pero las selecciones consiguientes hechas por B podrían devolver más filas. Eso es porque A no puede modificar filas que B ya leyó , hasta que A las libere. Sin embargo, A puede insertar nuevas filas que califiquen la condición where (y por lo tanto, la próxima vez que A ejecute una selección, obtendrá un resultado diferente con más filas: una lectura fantasma).
BornToCode
9

Como dice brb tea, depende de la implementación de la base de datos y del algoritmo que utilicen: MVCC o Two Phase Locking.

CUBRID (RDBMS de código abierto) explica la idea de estos dos algoritmos:

  • Bloqueo de dos fases (2PL)

La primera es cuando la transacción T2 intenta cambiar el registro A, sabe que la transacción T1 ya ha cambiado el registro A y espera hasta que se complete la transacción T1 porque la transacción T2 no puede saber si la transacción T1 se confirmará o transferirá. espalda. Este método se llama bloqueo de dos fases (2PL).

  • Control de concurrencia de múltiples versiones (MVCC)

El otro es permitir que cada una de ellas, las transacciones T1 y T2, tengan sus propias versiones modificadas. Incluso cuando la transacción T1 ha cambiado el registro A de 1 a 2, la transacción T1 deja el valor original 1 como está y escribe que la versión de la transacción T1 del registro A es 2. Luego, la siguiente transacción T2 cambia el registro A de 1 a 3, no de 2 a 4, y escribe que la versión de transacción T2 del registro A es 3.

Cuando se revierte la transacción T1, no importa si el 2, la versión de la transacción T1, no se aplica al registro A. Después de eso, si se confirma la transacción T2, la 3, la versión de transacción T2, se aplicará al registro A. Si la transacción T1 se confirma antes de la transacción T2, el registro A se cambia a 2 y luego a 3 en el momento de confirmar la transacción T2. El estado final de la base de datos es idéntico al estado de ejecución de cada transacción de forma independiente, sin ningún impacto en otras transacciones. Por tanto, satisface la propiedad ACID. Este método se denomina control de simultaneidad de múltiples versiones (MVCC).

El MVCC permite modificaciones concurrentes a costa de una mayor sobrecarga en la memoria (porque tiene que mantener diferentes versiones de los mismos datos) y cálculo (en el nivel REPETEABLE_READ no puede perder actualizaciones, por lo que debe verificar las versiones de los datos, como Hiberate hace con Optimistick Locking ).

En 2PL, los niveles de aislamiento de transacciones controlan lo siguiente :

  • Si se toman bloqueos cuando se leen datos y qué tipo de bloqueos se solicitan.

  • Cuánto tiempo se mantienen los bloqueos de lectura.

  • Si una operación de lectura que hace referencia a filas modificadas por otra transacción:

    • Bloquear hasta que se libere el bloqueo exclusivo de la fila.

    • Recupere la versión confirmada de la fila que existía en el momento en que comenzó la declaración o transacción.

    • Lea la modificación de datos no confirmada.

La elección de un nivel de aislamiento de transacciones no afecta los bloqueos que se adquieren para proteger las modificaciones de datos. Una transacción siempre obtiene un bloqueo exclusivo en cualquier dato que modifica y mantiene ese bloqueo hasta que se completa la transacción, independientemente del nivel de aislamiento establecido para esa transacción. Para operaciones de lectura, los niveles de aislamiento de transacciones definen principalmente el nivel de protección contra los efectos de las modificaciones realizadas por otras transacciones.

Un nivel de aislamiento más bajo aumenta la capacidad de muchos usuarios para acceder a los datos al mismo tiempo, pero aumenta la cantidad de efectos de simultaneidad , como lecturas sucias o actualizaciones perdidas, que los usuarios pueden encontrar.

Ejemplos concretos de la relación entre bloqueos y niveles de aislamiento en SQL Server (use 2PL excepto en READ_COMMITED con READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: no emita bloqueos compartidos para evitar que otras transacciones modifiquen los datos leídos por la transacción actual. Las transacciones READ UNCOMMITTED tampoco están bloqueadas por bloqueos exclusivos que evitarían que la transacción actual lea filas que han sido modificadas pero no confirmadas por otras transacciones. [...]

  • READ_COMMITED:

    • Si READ_COMMITTED_SNAPSHOT está configurado en OFF (el valor predeterminado): usa bloqueos compartidos para evitar que otras transacciones modifiquen filas mientras la transacción actual está ejecutando una operación de lectura. Los bloqueos compartidos también impiden que la declaración lea filas modificadas por otras transacciones hasta que se complete la otra transacción. [...] Los bloqueos de filas se liberan antes de que se procese la siguiente fila. [...]
    • Si READ_COMMITTED_SNAPSHOT se establece en ON, el motor de base de datos usa el control de versiones de fila para presentar cada declaración con una instantánea transaccionalmente coherente de los datos tal como existían al comienzo de la declaración. Los bloqueos no se utilizan para proteger los datos de las actualizaciones de otras transacciones.
  • REPETEABLE_READ: Los bloqueos compartidos se colocan en todos los datos leídos por cada declaración en la transacción y se mantienen hasta que se completa la transacción.

  • SERIALIZABLE: Los bloqueos de rango se colocan en el rango de valores clave que coinciden con las condiciones de búsqueda de cada declaración ejecutada en una transacción. [...] Los bloqueos de rango se mantienen hasta que se completa la transacción.

Gabrielgiussi
fuente
5

Los bloqueos siempre se toman a nivel DB: -

Documento oficial de Oracle: - Para evitar conflictos durante una transacción, un DBMS utiliza bloqueos, mecanismos para bloquear el acceso de otros a los datos a los que accede la transacción. (Tenga en cuenta que en el modo de confirmación automática, donde cada instrucción es una transacción, los bloqueos se mantienen solo para una instrucción). Después de establecer un bloqueo, permanece vigente hasta que la transacción se confirma o se deshace. Por ejemplo, un DBMS podría bloquear una fila de una tabla hasta que se hayan confirmado las actualizaciones. El efecto de este bloqueo sería evitar que un usuario obtenga una lectura sucia, es decir, leer un valor antes de que se convierta en permanente. (Acceder a un valor actualizado que no se ha confirmado se considera una lectura sucia porque es posible que ese valor se revierta a su valor anterior. Si lee un valor que luego se revirtió, habrá leído un valor no válido. )

La forma en que se establecen los bloqueos está determinada por lo que se denomina nivel de aislamiento de transacciones, que puede variar desde no admitir transacciones en absoluto hasta admitir transacciones que imponen reglas de acceso muy estrictas.

Un ejemplo de un nivel de aislamiento de transacciones es TRANSACTION_READ_COMMITTED, que no permitirá acceder a un valor hasta después de que se haya confirmado. En otras palabras, si el nivel de aislamiento de la transacción se establece en TRANSACTION_READ_COMMITTED, el DBMS no permite que se produzcan lecturas sucias. La interfaz Connection incluye cinco valores que representan los niveles de aislamiento de transacciones que puede utilizar en JDBC.

Goyal Vicky
fuente