Transacciones y mecanismos para su control.

Transacciones


Una transacción es una secuencia de operaciones en datos que tienen un principio y un final.


Una transacción es una operación de lectura y escritura secuencial. El final de una transacción puede ser guardar cambios (commit, commit) o ​​cancelar cambios (rollback, rollback). En relación con la base de datos, una transacción es una serie de consultas, que se tratan como una sola consulta.

Las transacciones deben satisfacer las propiedades de ACID


Atomicidad Una transacción se ejecuta completamente o no se realiza en absoluto.

Coherencia Al final de la transacción, no se deben infringir las restricciones impuestas a los datos (por ejemplo, restricciones en la base de datos). La consistencia implica que el sistema se transferirá de un estado correcto a otro correcto.

Aislamiento Las transacciones ejecutadas simultáneamente no deberían afectarse entre sí, por ejemplo, cambiando los datos que utiliza otra transacción. El resultado de las transacciones paralelas debe ser como si las transacciones se ejecutaran secuencialmente.

Sostenibilidad Una vez comprometidos, los cambios no deben perderse.

Registro de transacciones


El registro almacena los cambios realizados por las transacciones, garantiza la atomicidad y la estabilidad de los datos en caso de falla del sistema.


El registro contiene los valores que tenían los datos antes y después de su cambio por la transacción. La estrategia de registro de escritura anticipada requiere que agregue al registro un registro de valores anteriores antes del inicio y sobre los valores finales después de que se complete la transacción. En el caso de una parada repentina del sistema, la base de datos lee el registro en el orden inverso y descarta los cambios realizados por las transacciones. Una vez que se encuentra una transacción interrumpida, la base de datos la ejecuta y realiza cambios al respecto en el registro. Estando en el estado en el momento de la falla, la base de datos lee el registro en el orden directo y devuelve los cambios realizados por las transacciones. Por lo tanto, se preserva la estabilidad de las transacciones que ya se han comprometido y la atomicidad de la transacción interrumpida.

Simplemente volver a ejecutar transacciones erróneas no es suficiente para recuperarse.

Un ejemplo El usuario tiene $ 500 en la cuenta y decide retirarlos a través de un cajero automático. Se realizan dos transacciones. El primero lee el valor del saldo y si hay suficientes fondos en el saldo, le da dinero al usuario. El segundo resta la cantidad requerida del saldo. Suponga que un sistema falla y la primera operación falla, y la segunda falla. En este caso, no podemos volver a emitir dinero al usuario sin devolver el sistema a su estado original con un saldo positivo.

Niveles de aislamiento


Leer comprometido


El problema con una lectura sucia es que una transacción puede leer el resultado intermedio de otra transacción.

Un ejemplo El valor inicial del saldo es $ 0. T1 agrega $ 50 al saldo. T2 lee el valor del saldo ($ 50). T1 cancela los cambios y finaliza. T2 continúa la ejecución con datos de saldo incorrectos.

La solución es lectura confirmada, que prohíbe la lectura de datos modificados por una transacción. Si la transacción A ha cambiado algún conjunto de datos, entonces la transacción B, al acceder a estos datos, se ve obligada a esperar la transacción A.

Lectura repetible


El problema de los cambios perdidos (Actualizaciones perdidas). T1 guarda los cambios sobre los cambios en T2.

Un ejemplo El valor del saldo inicial es de $ 0 y dos transacciones reponen simultáneamente el saldo. T1 y T2 leen un saldo de $ 0. Luego, T2 agrega $ 200 a $ 0 y guarda el resultado. T1 agrega $ 100 a $ 0 y guarda el resultado. El resultado total es $ 100 en lugar de $ 300.

Problema de lectura irrepetible. La lectura repetida de los mismos datos devuelve valores diferentes.

Un ejemplo T1 lee un valor de saldo de $ 0. Luego, T2 agrega $ 50 al saldo y finaliza. T1 lee los datos nuevamente y detecta una discrepancia con el resultado anterior.

La lectura repetible asegura que la lectura repetida devolverá el mismo resultado. Los datos leídos por una transacción tienen prohibido cambiar en otros hasta que se complete la transacción. Si la transacción A ha leído algún conjunto de datos, entonces la transacción B, al acceder a estos datos, se ve obligada a esperar la transacción A.

Lectura ordenada (serializable)


Lecturas fantasma Dos consultas que seleccionan datos por alguna condición devuelven valores diferentes.

Un ejemplo T1 solicita el número de todos los usuarios cuyo saldo es mayor que $ 0 pero menor que $ 100. T2 resta $ 1 de un usuario con un saldo de $ 101. T1 vuelve a ejecutar la solicitud.

Lectura ordenada (serializable). Las transacciones se realizan como completamente secuenciales. Está prohibido actualizar y agregar registros sujetos a las condiciones de la solicitud. Si la transacción A solicitó datos de toda la tabla, entonces toda la tabla se congela para el resto de las transacciones hasta la transacción A.

Programador


Establece el orden en que las operaciones deben realizarse en transacciones paralelas


Proporciona un nivel específico de aislamiento. Si el resultado de las operaciones no depende de su orden, entonces dichas operaciones son conmutables (Permutable). Los comandos son leídos y las operaciones en diferentes datos. Las operaciones de lectura-escritura y escritura-escritura no son conmutativas. La tarea del planificador es alternar las operaciones realizadas por transacciones paralelas para que el resultado de la ejecución sea equivalente a la ejecución secuencial de las transacciones.

Mecanismos de control de concurrencia


Optimista basado en la detección y resolución de conflictos, pesimista basado en la prevención de conflictos


Con un enfoque optimista, varios usuarios tienen a su disposición copias de los datos. El primero que completó la edición guarda los cambios, el resto debe fusionar los cambios. Un algoritmo optimista permite que ocurra un conflicto, pero el sistema debe recuperarse del conflicto.

Con un enfoque pesimista, el primer usuario que captura datos evita que otros reciban datos. Si los conflictos son raros, es aconsejable elegir una estrategia optimista, ya que proporciona un mayor nivel de paralelismo.

Bloqueo


Si una transacción ha bloqueado datos, el resto de la transacción debe acceder a los datos al acceder a los datos.


Un bloque puede superponerse en una base de datos, tabla, fila o atributo. Shared Lock (Shared Lock) se puede imponer en los mismos datos mediante varias transacciones, permite la lectura de todas las transacciones (incluida la impuesta), prohíbe el cambio y la captura exclusiva. El bloqueo exclusivo puede ser impuesto por una sola transacción, permite cualquier acción de la transacción impuesta, prohíbe cualquier acción por parte del resto.

Un punto muerto es una situación en la que las transacciones están en modo de espera y duran indefinidamente


Un ejemplo La primera transacción está esperando la liberación de los datos capturados por la segunda, mientras que la segunda está esperando la liberación de los datos capturados por la primera.

Una solución optimista al problema del punto muerto permite que ocurra un punto muerto, pero luego restaura el sistema al deshacer una de las transacciones involucradas en el punto muerto.


Con cierta frecuencia, se realiza una búsqueda de puntos muertos. Uno de los métodos de detección es a tiempo, es decir, considerar que se produjo un punto muerto si la transacción lleva demasiado tiempo. Cuando se encuentra un punto muerto, una de las transacciones se revierte, lo que permite que se completen otras transacciones involucradas en el punto muerto. La elección de la víctima puede basarse en el valor de las transacciones o su antigüedad (esquemas de espera y muerte y espera de heridas).

A cada transacción T se le asigna una marca de tiempo TS que contiene la hora de inicio de la transacción.

Esperar-morir

Si TS (Ti) < TS (Tj) , Ti espera, de lo contrario Ti retrocede y comienza de nuevo con la misma marca de tiempo.

Si una transacción joven ha capturado un recurso y una más antigua solicita el mismo recurso, entonces se puede esperar una transacción más antigua. Si una transacción anterior ha capturado un recurso, se revertirá una transacción joven que solicite este recurso.

Herida de espera.

Si TS (Ti) < TS (Tj) , Tj retrocede y comienza de nuevo con la misma marca de tiempo, de lo contrario, Ti espera.

Si una transacción más joven ha capturado un recurso y una transacción más antigua está solicitando el mismo recurso, entonces la transacción más joven se revertirá. Si una transacción anterior ha capturado el recurso, entonces una transacción más joven que solicita este recurso puede esperar. La selección de la víctima basada en la antigüedad evita los puntos muertos, pero revierte las transacciones que no están en un estado de enclavamiento. El problema es que las transacciones pueden revertirse muchas veces porque Una transacción anterior puede contener un recurso durante mucho tiempo.

Una solución pesimista al problema de los puntos muertos no permite que la transacción comience a ejecutarse si existe el riesgo de un punto muerto


Para detectar puntos muertos, se construye un gráfico (un gráfico de espera, espera de gráfico), cuyos vértices son transacciones, y los bordes se dirigen desde las transacciones que están esperando que se liberen los datos a la transacción que capturó estos datos. Se cree que se produjo un punto muerto si el gráfico se repite. Construir un gráfico de espera, especialmente en bases de datos distribuidas, es un procedimiento costoso.

Bloqueo en dos fases: evita los puntos muertos al capturar todos los recursos utilizados por la transacción al comienzo de la transacción y liberarlos al final


Todas las operaciones de bloqueo deben preceder al primer desbloqueo. Tiene dos fases: la fase de crecimiento en la que se produce la captura de grabs y la fase de contracción en la que se produce la liberación de grabs. Si es imposible capturar uno de los recursos, la transacción comienza nuevamente. Es posible que una transacción no pueda capturar los recursos necesarios, por ejemplo, si varias transacciones compiten por los mismos recursos.

La confirmación de dos fases garantiza que la confirmación se ejecute en todas las réplicas de la base de datos.


Cada base de datos aporta información sobre los datos que se cambiarán al registro y corresponde al coordinador OK (Fase de votación). Después de que todos respondieron bien, el coordinador envía una señal obligando a todos a comprometerse. Después de confirmar el servidor, responden OK, si al menos uno no respondió OK, entonces el coordinador envía una señal para cancelar los cambios a todos los servidores (Fase de finalización).

Método de marca de tiempo


Una transacción anterior se revierte al intentar acceder a los datos involucrados en una transacción más joven


A cada transacción se le asigna una marca de tiempo TS correspondiente a la hora de inicio de la ejecución. Si Ti es anterior a Tj , entonces TS (Ti) < TS (Tj) .

Cuando una transacción se revierte, se le asigna una nueva marca de tiempo. Cada objeto de datos Q involucrado en la transacción está marcado con dos etiquetas. W-TS (Q) es la marca de tiempo de la transacción más joven que escribió con éxito a Q. R-TS (Q) es la marca de tiempo de la transacción más joven que completó un registro de lectura sobre Q.

Cuando la transacción T solicita leer datos Q , hay dos opciones posibles.

Si TS (T) < W-TS (Q) , es decir, los datos fueron actualizados por una transacción más joven, entonces la transacción T retrocede.

Si TS (T) > = W-TS (Q) , se realiza la lectura y R-TS (Q) se convierte en MAX (R-TS (Q), TS (T)) .

Cuando la transacción T solicita un cambio en los datos Q , son posibles dos opciones.

Si TS (T) < R-TS (Q) , es decir, los datos ya han sido leídos por una transacción más joven y si se realiza un cambio, surgirá un conflicto. La transacción T retrocede.

Si TS (T) < W-TS (Q) , es decir, la transacción intenta sobrescribir el valor más nuevo, la transacción T retrocede. En otros casos, el cambio se realiza y W-TS (Q) se vuelve igual a TS (T) .

No se requiere una costosa construcción de gráficos de espera. Las transacciones más antiguas dependen de las más nuevas, por lo tanto, no hay bucles en la columna de espera. No hay puntos muertos, porque las transacciones no se esperan, pero se deshacen de inmediato. Los sobornos en cascada son posibles. Si Ti retrocedió y Tj leyó los datos que Ti cambió, entonces Tj también debería retroceder. Si, al mismo tiempo, Tj ya ha sido comunicado, habrá una violación del principio de estabilidad.

Una solución a los retrocesos en cascada. Una transacción realiza todas las operaciones de escritura al final, y las transacciones restantes deben esperar la finalización de esta operación. Las transacciones están esperando una confirmación antes de leer.

Regla de escritura de Thomas: una variación del método de marca de tiempo en el que los datos actualizados por una transacción más joven no pueden ser sobrescritos por una más antigua


La transacción T solicita un cambio en los datos Q. Si TS (T) < W-TS (Q) , es decir, la transacción está intentando sobrescribir un valor más nuevo, la transacción T no se revierte como en el método de marca de tiempo.

Source: https://habr.com/ru/post/446662/


All Articles