[MySQL] Basado en MVCC y Read View, analice cómo los cuatro niveles de aislamiento de las transacciones reflejan su aislamiento en escenarios de lectura y escritura.


Los estudiantes que necesitan servidores en la nube y otros productos en la nube para aprender Linux pueden pasar a / --> Tencent Cloud <-- / --> Alibaba Cloud <-- / --> Huawei Cloud <-- / sitio web oficial, los servidores en la nube livianos son de bajo costo a 112 yuanes al año, y los nuevos usuarios pueden disfrutar de descuentos ultrabajos en su primer pedido.


 Tabla de contenido

1. Tres escenarios de concurrencia de bases de datos.

2. MVCC para escenarios de lectura y escritura. 

1. 3 (4) campos de columnas ocultas de registro

2. deshacer registro (deshacer registro)

3. Simular el escenario MVCC

3.1 escenario de actualización

3.2 eliminar escenario

3.3insertar

3.4seleccionar escena

4 、 Vista de lectura

5. La diferencia entre RR y RC

5.1 La diferencia entre la lectura actual y la lectura instantánea en el nivel RR

Ejemplo 1: instantánea raíz leída antes de la modificación de jly

Ejemplo 2: lectura instantánea de la raíz después de la modificación de jly

5.2Diferentes métodos de procesamiento de MySQL para los cuatro niveles de aislamiento 

3. Escribe la escena.


1. Tres escenarios de concurrencia de bases de datos.

Lectura-lectura: sin problemas y sin necesidad de control de concurrencia

Lectura y escritura: existen problemas de seguridad de subprocesos que pueden causar problemas de aislamiento de transacciones y pueden encontrar lecturas sucias, lecturas fantasmas y lecturas no repetibles.

Escritura-escritura: existen problemas de seguridad de subprocesos y puede haber problemas de pérdida de actualizaciones, como el primer tipo de pérdida de actualización y el segundo tipo de pérdida de actualización.

2. MVCC para escenarios de lectura y escritura. 

El control de concurrencia multiversión (MVCC) es un control de concurrencia sin bloqueo que se utiliza para resolver conflictos de lectura y escritura .

A la transacción se le asigna un ID de transacción que crece en una dirección y se guarda una versión para cada modificación. La versión está asociada con el ID de la transacción. La operación de lectura solo lee la instantánea de la base de datos antes de que comience la transacción. Entonces MVCC puede resolver los siguientes problemas para la base de datos:

Al leer y escribir la base de datos al mismo tiempo, se puede hacer sin bloquear la operación de escritura durante la operación de lectura, y la operación de escritura no necesita bloquear la operación de lectura, lo que mejora el rendimiento de la lectura y escritura simultáneas, y al mismo tiempo Resuelve problemas de aislamiento de transacciones, como lecturas sucias, lecturas fantasma y lecturas no repetibles, pero no resuelve el problema de las actualizaciones perdidas.

1. 3 (4) campos de columnas ocultas de registro

Al crear una tabla, MySQL creará 3 campos de columnas ocultas de registros además de las columnas requeridas por el usuario.

DB_TRX_ID: 6 bytes, esta columna registra el ID de transacción (modificación/inserción) de la última modificación de cada fila.

DB_ROLL_PTR: 7 bytes, puntero de reversión, que apunta a la versión anterior de este registro (simplemente entendido como que apunta a la versión histórica, estos datos generalmente se encuentran en el registro de deshacer)

DB_ROW_ID: 6 bytes, ID de incremento automático implícito (clave primaria oculta), si la tabla de datos no tiene una clave primaria, InnoDB generará automáticamente un índice agrupado con DB_ROW_ID

El cuarto campo de columna oculto: en realidad, hay un indicador de campo oculto que identifica si la fila de datos se elimina.

Por ejemplo, al crear e insertar un dato, la estructura de la tabla real debería ser así:

nombre

edad

DB_TRX_ID

DB_ROLL_PTR

DB_ROW_ID

Zhang San

20

Crea el ID de la transacción.

nulo

1 (clave primaria implícita)

2. deshacer registro (deshacer registro)

MySQL se ejecuta en la memoria como un proceso demonio. Deshacer registro es un búfer de memoria en MySQL para guardar datos de registro.

3. Simular el escenario MVCC

3.1 escenario de actualización

Existe un ID de transacción de 10. Actualice la tabla de información anterior y cambie el nombre de Zhang San a Li Si:

1. Como desea modificarlo, primero debe agregar un bloqueo de fila al registro.

2. Antes de la modificación, copie los datos redirigidos al registro de deshacer (copie mientras escribe, los datos originales están en la tabla, los datos copiados están en el registro de deshacer, suponiendo que la dirección de datos copiados es 0XAA)

3. Mientras modifica los datos originales, modifique el campo oculto DB_TRX_ID a 10 y el puntero de reversión DB_ROLL_PTR a 0XAAAAAAAAA.

4. Se envía la transacción 10 y se libera el bloqueo de fila.

nombre

edad

DB_TRX_ID

DB_ROLL_PTR

DB_ROW_ID

Juan Pérez

20

10

0XAAAAAAAA

1 (clave primaria implícita)

En este momento, hay otra transacción 11, que necesita actualizar los registros en la tabla de información y cambiar la edad de la fila de Li Si a 30:

1. Como desea modificarlo, primero debe agregar un bloqueo de fila al registro.

2. De manera similar, copie la fila correspondiente en la tabla actual para deshacer el registro, asumiendo la dirección 0XBBBBBBBB.

3. Mientras modifica los datos originales, modifique el campo oculto DB_TRX_ID a 10 y el puntero de reversión DB_ROLL_PTR a 0XAAAAAAAAA.

nombre

edad

DB_TRX_ID

DB_ROLL_PTR

DB_ROW_ID

Juan Pérez

30

11

0XBBBBBBBB

1 (clave primaria implícita)

Cada versión del registro de deshacer se denomina instantánea. Además de la cadena de versiones, también puede registrar el SQL inverso para prepararse para la reversión de datos (como eliminar datos y el registro puede guardar datos insertados)

3.2 eliminar escenario

Eliminar datos no significa borrarlos, simplemente configure la bandera oculta para eliminar. También se pueden formar versiones.

3.3insertar

Insertar es una inserción. Al insertar, solo necesita registrar sus declaraciones de eliminación correspondientes en el registro de deshacer. Al revertir, solo necesita ejecutar estas declaraciones de eliminación. Si se confirma la transacción actual, el registro de deshacer eliminará los datos de la copia de seguridad. (Es posible que aún haya otras transacciones accediendo a actualización y eliminación, y los datos de reversión del registro de deshacer no se eliminarán inmediatamente después de la confirmación)

3.4seleccionar escena

En el nivel RR de MySQL, la operación de escritura de una transacción no afecta la operación de lectura de otra transacción. Las adiciones, eliminaciones y modificaciones son modificaciones de los datos más recientes, pero la lectura puede requerir la lectura de versiones históricas.

Lectura actual: lee el último registro, que es la lectura actual. Las adiciones, eliminaciones y modificaciones se denominan lectura actual, y la selección también puede ser la lectura actual, como seleccionar bloqueo en modo compartido (bloqueo compartido), seleccionar para actualizar

Lectura instantánea: lea la versión histórica. Las lecturas de instantáneas no están bloqueadas.

Cuando se agregan, eliminan y modifican varias transacciones al mismo tiempo, es la lectura actual y debe bloquearse. Si la selección también está bloqueada, el nivel de aislamiento es la serialización. Si la selección es una lectura instantánea, no afectará la lectura actual de adiciones, eliminaciones y modificaciones, por lo que no se requiere bloqueo y la ejecución paralela es altamente eficiente. El nivel de aislamiento de la transacción determina si los datos históricos de lectura seleccionados son lectura actual o lectura instantánea. (Si la vista de lectura está actualizada)

Entonces, ¿cómo garantizar que diferentes transacciones vean contenido diferente? ¿La transacción que se produce primero debería ver las modificaciones realizadas por las transacciones posteriores? Read View realiza un juicio de visibilidad.

4 、 Vista de lectura

MySQL genera la Vista de lectura cuando una transacción realiza una lectura instantánea por primera vez y registra y mantiene la ID de la transacción actualmente activa en el sistema. Read View es una clase en el código fuente de MySQL y se usa esencialmente con MVCC para determinar qué instantáneas puedo ver y cuáles no.

Cuando una transacción realiza una lectura de instantánea selecta, MySQL creará un nuevo objeto para ella y utilizará sus condiciones internas para determinar qué versión de los datos puede ver la transacción actual. Los datos visibles pueden ser los datos más recientes o los datos más recientes. Esta línea registra una determinada versión de los datos en el registro de deshacer, que está determinada por el nivel de aislamiento.

La siguiente es una estructura simplificada de ReadView:

class ReadView {
    // 省略...
    private:
    /** 高水位,大于等于这个ID的事务均不可见*/
    trx_id_t m_low_limit_id
    /** 低水位:小于这个ID的事务均可见 */
    trx_id_t m_up_limit_id;
    /** 创建该 Read View 的事务ID*/
    trx_id_t m_creator_trx_id;
    /** 创建视图时的活跃事务id列表*/
    ids_t m_ids;//ids_t集合类型 
    /** 配合purge,标识该视图不需要小于m_low_limit_no的UNDO LOG,
    * 如果其他视图也不需要,则可以删除小于m_low_limit_no的UNDO LOG*/
    trx_id_t m_low_limit_no;
    /** 标记视图是否被关闭*/
    bool m_closed;
    // 省略...
};
m_ids; //一张列表,用来维护Read View生成时刻,系统正活跃的事务ID
up_limit_id; //记录m_ids列表中事务ID最小的ID
low_limit_id; //ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1
creator_trx_id //创建该ReadView的事务ID

Entonces, ¿qué datos pueden leer las transacciones y qué datos no pueden verse? Vea abajo:

Para resumir: por ejemplo, soy un estudiante de tercer año. Puedo ver los datos de búsqueda de empleo de los estudiantes de último año que ingresaron a la escuela antes que yo, pero los de último año no pueden ver los datos de búsqueda de empleo de mí que ingresé a la escuela más tarde. De manera similar, al tomar una instantánea, puedo ver:

Transacciones enviadas:

1. Creator_trx_id (el ID de la transacción que creó la instantánea) == DB_TRX_ID (el ID de la transacción que modificó por última vez la fila en el registro de deshacer)

2. DB_TRX_ID (el ID de transacción de la fila que se modificó por última vez en el registro de deshacer) <up_limit_id (el ID con el ID de transacción más pequeño en la lista m_ids que forma la instantánea)

Transacciones en m_ids (ID de transacción activa) cuando se creó la instantánea:

1. Los ID de transacción en la instantánea no son necesariamente consecutivos. El rango de ID de transacción en la instantánea es up_limit_id<=ID<low_limit_id. Si DB_TRX_ID (el ID de transacción de la modificación más reciente de la fila en el registro de deshacer) está en este rango, pero no existe dicho ID en la lista m_ids de la tabla de instantáneas, significa que la transacción se ha confirmado y puede ser visto en la instantánea actual. Si la lista m_ids tiene este ID, indica que la transacción con este ID en la instantánea actual todavía está activa y no se puede ver.

No puedo ver:

Cosas nuevas después de crear la instantánea:

1. DB_TRX_ID (el ID de transacción de la última fila modificada en el registro de deshacer) >= low_limit_id (el siguiente ID que no ha sido asignado por el sistema cuando se genera la instantánea)

Si se descubre que no se debe ver la versión actual, el siguiente paso es recorrer la siguiente versión hasta que se cumplan las condiciones.

nombre

edad

DB_TRX_ID

DB_ROLL_PTR

DB_ROW_ID

Zhang San

28

Crea el ID de la transacción.

nulo

1 (clave primaria implícita)

La cadena de versiones en el registro de deshacer en este momento:

Cuando la transacción 2 realiza la lectura de instantáneas en la fila modificada, recorre las instantáneas en el registro de deshacer para determinar qué versión de la instantánea debo leer al leer la instantánea de la fila esta vez.

5. La diferencia entre RR y RC

5.1 La diferencia entre la lectura actual y la lectura instantánea en el nivel RR

Preparación:

--将全局隔离级别设置为可重复读(需重启)
mysql> set global transaction isolation level REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
--创建一张表
mysql> create table if not exists account(
    -> id int primary key,
    -> age int not null,
    -> name varchar(20) not null
    -> )ENGINE=InnoDB DEFAULT CHARSET=UTF8;
Query OK, 0 rows affected (0.26 sec)
--插入一条数据
mysql> insert into account values (1,18,'张三');
Query OK, 1 row affected (0.04 sec)
Ejemplo 1: instantánea raíz leída antes de la modificación de jly

Usuario: jly

--1、启动事务
mysql> begin;
Query OK, 0 rows affected (0.01 sec)
--2、进行快照读
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  18 | 张三   |
+----+-----+--------+
1 row in set (0.00 sec)
--3、更新数据,修改id为1的字段的年龄为20
mysql> update account set age=20 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
--4、对事务进行提交
mysql> commit;
Query OK, 0 rows affected (0.04 sec)

Usuario: raíz

--当上方用户执行完第一步时,root同时启动事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--当上方用户执行完第二步时,root同时进行快照读,读取的结果一样
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  18 | 张三   |
+----+-----+--------+
1 row in set (0.01 sec)
--当上方用户执行完第三步时,root进行快照读,发现年龄的修改并没有被读到
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  18 | 张三   |
+----+-----+--------+
1 row in set (0.00 sec)
--当上方用户执行完第四步提交事务时,root再次进行快照读,发现年龄的修改还是没有被读到
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  18 | 张三   |
+----+-----+--------+
1 row in set (0.00 sec)
--但是此时root使用当前读,使能够读到年龄的修改的
mysql> select* from account lock in share mode;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  20 | 张三   |
+----+-----+--------+
1 row in set (0.01 sec)
Ejemplo 2: lectura instantánea de la raíz después de la modificación de jly

Usuario: jly

--1、启动事务
mysql> begin;
Query OK, 0 rows affected (0.01 sec)
--2、进行快照读
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  20 | 张三   |
+----+-----+--------+
1 row in set (0.00 sec)
--3、更新数据,修改id为1的字段的年龄为30
mysql> update account set age=30 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
--4、提交事务
mysql> commit;
Query OK, 0 rows affected (0.03 sec)

Usuario: raíz

--1、同时启动事务
mysql> begin;
Query OK, 0 rows affected (0.01 sec)
--当上方用户执行完第四步提交事务时,root进行快照读,发现读到的数据是被修改过的
mysql> select* from account;
+----+-----+--------+
| id | age | name   |
+----+-----+--------+
|  1 |  30 | 张三   |
+----+-----+--------+
1 row in set (0.00 sec)

A través del Ejemplo 1, podemos encontrar que: antes de enviar jly, la selección raíz lee los datos antes de modificarlos;

A través del Ejemplo 2, podemos encontrar que después de que jly envía la selección raíz, se leen los datos modificados.

Esto se debe a que cuando se lee una transacción, MySQL generará un objeto de vista de lectura. Como se mencionó en el capítulo anterior que presenta la vista de lectura, la vista de lectura es esencialmente una clase que se utiliza para determinar qué instantáneas puedo ver y cuáles no. .

El momento de generación de la vista de lectura es diferente, lo que afectará la visibilidad de las transacciones.

5.2Diferentes métodos de procesamiento de MySQL para los cuatro niveles de aislamiento 

La diferencia en el tiempo de generación de la Vista de lectura da como resultado diferentes resultados de lectura de instantáneas bajo diferentes niveles de aislamiento de RC y RR:

Lectura repetible: la primera lectura de instantánea de un registro por parte de una transacción en el nivel RR creará una instantánea y un objeto de vista de lectura para registrar otras transacciones activas en el sistema actual; cuando se vuelva a llamar a la lectura de instantánea más tarde, la misma vista de lectura seguirá siendo se usa, de modo que siempre que la transacción actual use la lectura de instantáneas antes de que otras transacciones confirmen las actualizaciones, las lecturas de instantáneas posteriores usan la misma vista de lectura, por lo que las modificaciones posteriores no son visibles; es decir, en el nivel RR, cuando la lectura de instantáneas genera una lectura Vista, la Vista de lectura registrará las instantáneas de todas las demás transacciones activas en este momento, y las modificaciones de estas transacciones son invisibles para la transacción actual. Sólo se pueden ver las modificaciones realizadas por transacciones creadas antes de la Vista de lectura.

Confirmación de lectura: en una transacción a nivel de RC, cada lectura de instantánea generará una nueva instantánea y una Vista de lectura. Es por eso que podemos ver las actualizaciones de otras transacciones en el nivel de RC. Es precisamente cuando RC lee una instantánea que se forma una Vista de lectura, por lo que RC tiene un problema de lectura no repetible.

Lectura no confirmada: lectura actual. No hay aislamiento.

Serialización: actualmente leyendo, mientras que agregar, eliminar y modificar están bloqueados, la selección también está bloqueada.

3. Escribe la escena.

Entiéndalo directamente como la lectura actual.

Supongo que te gusta

Origin blog.csdn.net/gfdxx/article/details/131524580
Recomendado
Clasificación