MVCC como una forma de garantizar el aislamiento de la transacción

Hola Habr Me llamo Vladislav Rodin. Actualmente, soy el jefe del curso High Load Architect en OTUS, y también doy cursos sobre arquitectura de software.

Especialmente para el comienzo de un nuevo set para el curso "Arquitecto de altas cargas" , escribí un pequeño material, que con gusto comparto con ustedes.



Introducción


La última vez, hablamos con usted sobre las consecuencias de debilitar el aislamiento de transacciones en bases de datos. Hoy discutiremos con más detalle una de las formas de garantizar este aislamiento y evitar las anomalías consideradas. Como habrás notado, en el último artículo se distinguieron dos enfoques: uno se basó en el hecho de que los registros tienen algunas versiones y el segundo en que bloquearemos la grabación de una forma u otra . Por lo tanto, se distinguen dos clases de bases de datos: versionadas y bloqueadoras . Hoy hablaremos sobre qué son los controladores de versión, y dejemos la consideración de los bloqueadores la próxima vez.

Versionionistas


Como dije, uno de los enfoques se basa en el control de versiones. También se llama el enfoque optimista o MVCC (control de concurrencia multiversion) . De hecho, se produce el almacenamiento de versiones para transacciones activas.

¿Dónde se almacenan las versiones?


La implementación del mecanismo depende de la base de datos. Daré ejemplos de algunos de ellos.

PostgreSQL


Cada transacción se caracteriza por algún id-shnik. Las transacciones de id-shnik crecen de manera monótona. Cualquier línea tiene 2 atributos que representan metainformación para proporcionar el mecanismo: updated_by_id - id de la transacción que actualizó este registro por última vez y deleted_by_id - id de la transacción que eliminó este registro. Cuando llega una nueva transacción, la base de datos determina los apodos de identificación de las transacciones que se realizan actualmente, los cambios realizados por estas transacciones serán ignorados dentro de la transacción entrante. Resulta que la transacción entrante funciona como si fuera su versión de los datos. Las versiones antiguas de datos se almacenan en el mismo lugar que las actuales. Si llega la actualización, se agrega otra línea y este registro se activa. También está claro que para el correcto funcionamiento de este esquema, se requiere un "recolector de basura":si algún registro ha eliminado_by_id = 100, y el mínimo id-shnik entre las transacciones actuales es 150, entonces este registro debe eliminarse.

MySQL (motor InnoDB)


Solo la versión actual se almacena en la base de datos MySQL. Cuando llega la actualización, se corrigen los datos dentro del archivo de la tabla. Después de ajustar los datos, la versión anterior está en el registro de reversión. Hay varios registros de reversión en MySQL (son diferentes para insert'ov y update'ov). Si una transacción necesita una versión anterior de la línea, el sistema va a deshacer el registro y restaura la versión necesaria. La versión también está determinada por la identificación de la transacción.

Oráculo


El esquema es similar a MySQL: las versiones actuales se almacenan en el archivo de datos, las versiones antiguas se restauran gracias al registro de deshacer. El registro de deshacer en Oracle se reescribe cíclicamente. Por lo tanto, una situación es posible cuando una transacción necesita una versión muy antigua del registro, pero en el registro de deshacer ya no está allí. Si se produce esta situación, la transacción fallará.

MS SQL


MS SQL permite la inclusión de los modos versionioner y blocker. Para habilitar el modo versionado en la configuración de la base de datos, debe habilitar las instantáneas. En MS SQL hay una tabla del sistema (tempdb), que está diseñada para almacenar tablas temporales. Es tempdb que se utiliza para almacenar versiones antiguas, mientras que la tabla contiene las versiones actuales. El proceso del sistema monitorea que en tempdb hay versiones a las que nadie se refiere, se pueden eliminar. Si la transacción es de larga duración, las versiones se guardarán para ella. Tempdb crece, alcanza su tamaño máximo, MS SQL asigna un poco de espacio en disco. Si finaliza, no se pueden realizar transacciones con aislamiento de instantánea. Si se utiliza este modo de operación, es necesario monitorear transacciones largas,porque la reversión de tal transacción a tiempo puede costar tanto como funciona, y tal vez un poco más.

Conflictos


Este enfoque se llama optimista, porque esperamos que no haya conflicto si se ejecutan transacciones paralelas de cambio de datos. ¿Qué pasa en caso de conflicto? Suponga que la transacción T1 cambia 10,000 registros y la transacción T2 cambia 1 registro en paralelo. Si sucedió que este registro 1 está incluido en esos 10,000, entonces una de las transacciones se revertirá: si T1 se ejecuta primero, entonces T2 se revertirá, de lo contrario será al revés.

Mecanismo de retroceso


El mecanismo de reversión de transacciones en versiones versionadas depende de la implementación. Por ejemplo, en PostgreSQL, una transacción se marca como evacuada y el vacío libera espacio en disco. Tal mecanismo es lo suficientemente rápido. En Oracle, para la reversión, los datos se restauran desde el registro de deshacer. En este caso, el tiempo de funcionamiento aumenta, sin embargo, sigue siendo mucho más rápido que en los armarios. MySQL funciona de la misma manera que Oracle.

Conclusión


El enfoque optimista es bueno porque el escritor no bloquea al lector, el lector simplemente lee su versión de los datos. Por lo tanto, el control de versiones es beneficioso si la carga principal es leer más que escribir (blog, informes y otros casos en los que necesita leer con frecuencia y mucho).



Obtenga más información sobre el curso aquí.



All Articles