Relación de niveles de aislamiento de transacción con lockings en la tabla

He leído acerca de 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 locking que cada aislamiento de transacción toma en 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 están los tres fenómenos que pueden ocurrir en el aislamiento de transacciones
Dirty Read – sin locking
Lectura no repetible : sin lectura sucia como locking de datos confirmados
Phantom Read : locking en el bloque de sql (que se selecciona mediante el uso de la consulta de selección)

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

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

Quiero entender el locking que cada aislamiento de transacción toma en la mesa

Por ejemplo, tiene 3 procesos concurrentes A, B y C. A inicia una transacción, escribe datos y confirma / restituye (según los resultados). B solo ejecuta una instrucción SELECT para leer datos. C lee y actualiza datos. Todos estos procesos funcionan en la misma mesa T.

  • LEER SIN COMPROMISO: sin locking en la mesa. Puede leer datos en la tabla mientras escribe en ella. Esto significa que A escribe datos (sin compromiso) y B puede leer estos datos sin compromiso y usarlos (para cualquier propósito). Si A ejecuta una reversión, B aún 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 ocasionar agujeros de datos en tablas no relacionadas físicamente (sí, dos tablas pueden ser relacionadas de forma lógica pero no física en aplicaciones del mundo real = \).
  • LEA COMPROMETIDO: bloquee los datos confirmados. Puede leer los datos que solo se han confirmado. Esto significa que A escribe datos y B no puede leer los datos guardados por A hasta que A ejecute un compromiso. 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.
  • REPEATABLE READ – locking en el bloque de sql (que se selecciona mediante el uso de la consulta de selección). Esto significa que B lee los datos bajo alguna condición, es decir, WHERE aField > 10 AND aField < 20 , A inserta datos donde aField valor de aField está entre 10 y 20, luego B lee los datos nuevamente y obtiene un resultado diferente.
  • SERIALIZABLE: bloquear en la 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 en 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 grandes 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 a nivel jdbc / hibernate o en DB también

Usando JDBC, lo defines usando Connection#setTransactionIsolation .

Usando Hibernate:

 2 

Dónde

  • 1: LEER SIN COMPROMISO
  • 2: LEER COMPROMETIDO
  • 4: LEÍDO REPETIBLE
  • 8: SERIALIZABLE

Configuración de Hibernate tomada desde aquí (lo siento, está en español).

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

  • Nivel de aislamiento de MySQL
  • Nivel de aislamiento de SQL Server
  • Nivel de aislamiento de Informix (Nota personal: nunca olvidaré la sentencia SET ISOLATION TO DIRTY READ ).

y así sucesivamente...

Como dice brb tea, depende de la implementación de la base de datos y del algoritmo que utilicen: MVCC o locking de dos fases.

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

  • Bloqueo de dos fases (2PL)

El primero 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 locking 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 transaccional T1 del registro A es 2. Entonces, 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 la 2, la versión de transacción T1, no se aplica al registro A. Después de eso, si la transacción T2 se confirma, el 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 lo tanto, satisface la propiedad ACID. Este método se llama control de concurrencia de varias 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 computación (en el nivel REPETEABLE_READ no puede perder actualizaciones, por lo que debe verificar las versiones de los datos, como Hiberate lo hace con Optimistick Locking ).

En 2PL, los niveles de aislamiento de transacción controlan lo siguiente :

  • Si los lockings se toman cuando se leen los datos, y qué tipo de lockings se solicitan.

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

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

    • Bloquea hasta liberar el locking exclusivo en la fila.

    • Recupere la versión confirmada de la fila que existía en el momento en que se inició la statement o la transacción.

    • Lea la modificación de datos no confirmada.

Elegir un nivel de aislamiento de transacción no afecta los lockings que se adquieren para proteger las modificaciones de datos. Una transacción siempre obtiene un locking exclusivo sobre cualquier dato que modifica y mantiene ese locking hasta que la transacción se complete, independientemente del nivel de aislamiento establecido para esa transacción. Para las operaciones de lectura, los niveles de aislamiento de las transacciones definen principalmente el nivel de protección frente a 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 el número de efectos de concurrencia , como las lecturas sucias o las actualizaciones perdidas, que los usuarios pueden encontrar.

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

  • READ_UNCOMMITED: no ejecute lockings compartidos para evitar que otras transacciones modifiquen datos leídos por la transacción actual. Las transacciones LEED UNCOMMITTED tampoco están bloqueadas por lockings exclusivos que evitarían que la transacción actual leyera filas que han sido modificadas pero no confirmadas por otras transacciones. […]

  • READ_COMMITED:

    • Si READ_COMMITTED_SNAPSHOT está establecido en DESACTIVADO (valor predeterminado): utiliza lockings compartidos para evitar que otras transacciones modifiquen filas mientras la transacción actual está ejecutando una operación de lectura. Los lockings compartidos también bloquean la instrucción de lectura de filas modificadas por otras transacciones hasta que se complete la otra transacción. […] Los lockings de fila se liberan antes de procesar la siguiente fila. […]
    • Si READ_COMMITTED_SNAPSHOT está establecido en ON, el motor de base de datos utiliza el control de versiones de filas para presentar cada instrucción con una instantánea consistente de transacciones de los datos tal como existía al comienzo de la instrucción. Los lockings no se usan para proteger los datos de las actualizaciones de otras transacciones.
  • REPETEABLE_READ: los lockings compartidos se colocan en todos los datos leídos por cada instrucción en la transacción y se mantienen hasta que finaliza la transacción.

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

Los lockings siempre se toman a nivel DB:

Documento oficial de Oracle: para evitar conflictos durante una transacción, un DBMS utiliza lockings, mecanismos para bloquear el acceso de terceros a los datos a los que la transacción accede. (Tenga en cuenta que en el modo de autocompromiso, donde cada statement es una transacción, los lockings se mantienen para una sola instrucción). Después de establecer un locking, permanece en vigor hasta que la transacción se confirma o se retrotrae. Por ejemplo, un DBMS podría bloquear una fila de una tabla hasta que se hayan confirmado las actualizaciones. El efecto de este locking sería evitar que un usuario obtenga una lectura sucia, es decir, leer un valor antes de que se vuelva permanente. (El acceso a un valor actualizado que no se ha confirmado se considera una lectura sucia porque es posible que ese valor se retrotrae a su valor anterior. Si lee un valor que luego se retrotrae, habrá leído un valor no válido. )

La forma en que se establecen los lockings viene determinada por lo que se denomina un nivel de aislamiento de transacción, que puede ir desde no admitir transacciones en absoluto hasta respaldar transacciones que imponen reglas de acceso muy estrictas.

Un ejemplo de un nivel de aislamiento de transacción es TRANSACTION_READ_COMMITTED, que no permitirá que se acceda a un valor hasta después de que se haya confirmado. En otras palabras, si el nivel de aislamiento de la transacción está establecido en TRANSACTION_READ_COMMITTED, el DBMS no permite que ocurran lecturas sucias. La conexión de interfaz incluye cinco valores que representan los niveles de aislamiento de transacción que puede usar en JDBC.