java - tipos - Relación de niveles de aislamiento de transacción con bloqueos en la tabla
transacciones sql (3)
Quiero entender el bloqueo 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 bloqueo 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 - bloqueo 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 dondeaField
valor deaField
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:
<property name="hibernate.connection.isolation">2</property>
Dónde
- 1: LEER SIN COMPROMISO
- 2: LEER COMPROMETIDO
- 4: LEÍDO REPETIBLE
- 8: SERIALIZABLE
Configuración de Hibernate tomada desde here (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...
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 bloqueo 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 bloqueo
Lectura no repetible : sin lectura sucia como bloqueo de datos confirmados
Phantom Read : bloqueo 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
Como dice brb tea, depende de la implementación de la base de datos y del algoritmo que utilicen: MVCC o bloqueo de dos fases.
CUBRID (RDBMS de código abierto) explains 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 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 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 bloqueos se toman cuando se leen los datos, y qué tipo de bloqueos se solicitan.
Cuánto tiempo se mantienen los bloqueos de lectura.
Si una operación de lectura hace referencia a filas modificadas por otra transacción:
Bloquea hasta liberar el bloqueo exclusivo en la fila.
Recupere la versión confirmada de la fila que existía en el momento en que se inició la declaración o la transacción.
Lea la modificación de datos no confirmada.
Elegir un nivel de aislamiento de transacción no afecta los bloqueos que se adquieren para proteger las modificaciones de datos. Una transacción siempre obtiene un bloqueo exclusivo sobre cualquier dato que modifica y mantiene ese bloqueo 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 bloqueos y niveles de aislamiento en SQL Server (use 2PL excepto en READ_COMMITED con READ_COMMITTED_SNAPSHOT = ON)
READ_UNCOMMITED: no ejecute bloqueos compartidos para evitar que otras transacciones modifiquen datos leídos por la transacción actual. Las transacciones LEED UNCOMMITTED tampoco están bloqueadas por bloqueos 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 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 bloquean la instrucción de lectura de filas modificadas por otras transacciones hasta que se complete la otra transacción. [...] Los bloqueos 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 bloqueos no se usan 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 instrucción en la transacción y se mantienen hasta que finaliza 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 instrucción ejecutada en una transacción. [...] Los bloqueos de rango se mantienen hasta que finaliza la transacción.
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 terceros a los datos a los que la transacción accede. (Tenga en cuenta que en el modo de autocompromiso, donde cada declaración es una transacción, los bloqueos se mantienen para una sola instrucción). Después de establecer un bloqueo, 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 bloqueo 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 bloqueos 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.