MySQL en acción: bloqueos

Por favor agregue la descripción de la imagen

Escenarios concurrentes

Cuando aprendemos MySQL, a menudo mencionamos las cuatro características de las cosas, atomicidad, consistencia, aislamiento y durabilidad. Entonces, ¿cómo se logra el aislamiento?

La esencia del aislamiento es controlar la concurrencia , si las sentencias SQL se ejecutan en serie. Entonces no habrá concepto de aislamiento en las cuatro características de la base de datos, y no habrá problemas como lecturas sucias, lecturas no repetibles y lecturas fantasma.

Solo hay cuatro tipos de operaciones simultáneas en la base de datos: escritura-escritura, lectura-lectura, lectura-escritura y escritura-lectura.

escribe escribe

Cuando la transacción A actualiza un registro, ¿la transacción B puede actualizar el mismo registro al mismo tiempo?

La respuesta es definitivamente no, de lo contrario causará el problema de la escritura sucia.¿Cómo evitar la escritura sucia? La respuesta es cerrar

leer leer

Las operaciones de lectura de MySQL no están bloqueadas de forma predeterminada, por lo que se pueden leer en paralelo

leer-escribir y escribir-leer

Basado en los diferentes niveles de tolerancia de operaciones concurrentes en varios escenarios, MySQL ha desarrollado un concepto de aislamiento . Puede elegir el nivel de aislamiento según el escenario empresarial.

√ significa que sucederá, × significa que no sucederá

nivel de aislamiento lectura sucia lectura no repetible alucinaciones
leer sin compromiso
leer comprometido ×
lectura repetible × ×
serializable (serializable) × × ×

Bloqueos en MySQL

bloqueo de nivel de fila

Hay dos tipos de bloqueos de nivel de fila en el motor de almacenamiento InnoDB:

  1. Bloqueo compartido (bloqueo compartido, denominado bloqueo S), cuando una transacción necesita leer un registro, primero debe adquirir el bloqueo S para cambiar el registro
  2. Bloqueo exclusivo (bloqueo exclusivo, denominado bloqueo X), cuando una transacción desea cambiar un registro, primero debe obtener el bloqueo X del registro

Si la transacción T1 adquiere el bloqueo S de un registro, la transacción T2 también accede a este registro. Si la transacción T2 quiere adquirir el bloqueo S de este registro nuevamente, puede tener éxito. Esta situación se denomina compatibilidad de bloqueo. Si la transacción T2 desea adquirir el bloqueo X de este registro nuevamente, esta operación se bloqueará hasta que la transacción T1 confirme el S bloquear liberar

Si la transacción T1 adquiere el bloqueo X de un registro, entonces, ya sea que la transacción T2 quiera adquirir el bloqueo S o el bloqueo X del registro a continuación, se bloqueará hasta que se confirme la transacción 1, lo que se denomina incompatibilidad de bloqueo.

Varias transacciones pueden leer registros al mismo tiempo, es decir, los bloqueos compartidos no se excluyen mutuamente, pero los bloqueos compartidos bloquean los bloqueos exclusivos. Exclusión mutua entre bloqueos exclusivos

La relación de compatibilidad entre S lock y X lock es la siguiente

compatibilidad Bloqueo X Bloqueo S
Bloqueo X mutuamente excluyentes mutuamente excluyentes
Bloqueo S mutuamente excluyentes compatible

actualizar, eliminar e insertar agregará automáticamente bloqueos exclusivos a los datos involucrados, y la declaración de selección no agregará ningún bloqueo de forma predeterminada.

¿En qué circunstancias se bloqueará la operación de lectura?

  1. seleccione... bloquear en modo compartido, agregue S lock a los registros de lectura
  2. seleccione ... para actualizar, agregue bloqueo X a los registros de lectura
  3. Lea registros en una transacción, agregue S lock a los registros de lectura
  4. El nivel de aislamiento de la transacción está por debajo de SERIALIZABLE y el bloqueo S se aplica a los registros de lectura

Hay tres algoritmos para bloqueos de fila en InnoDB:

  1. Bloqueo de registro: bloquear un solo registro
  2. Gap Lock: Gap lock, bloquea el espacio frente al registro y no permite que se inserten registros
  3. Bloqueo de tecla siguiente: bloquee los datos y el espacio frente a los datos al mismo tiempo, es decir, ni los datos ni el espacio frente a los datos pueden insertar registros

Escriba una demostración para demostrar

CREATE TABLE `girl` (
  `id` int(11) NOT NULL,
  `name` varchar(255),
  `age` int(11),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into girl values
(1, '西施', 20),
(5, '王昭君', 23),
(8, '貂蝉', 25),
(10, '杨玉环', 26),
(12, '陈圆圆', 20);

Bloqueo de registro

bloquear un solo registro

Por ejemplo, agregue un bloqueo de registro a los datos con un valor de identificación de 8, el diagrama esquemático es el siguiente

inserte la descripción de la imagen aquí
Record Lock también se divide en S lock y X lock, y la compatibilidad es la misma que se describió anteriormente.

El tipo de bloqueo que se agrega a la ejecución de SQL está restringido por muchas condiciones, como el nivel de aislamiento de la transacción y el índice utilizado durante la ejecución (como índice agrupado, índice no agrupado, etc.), por lo que no se analizará. en detalle, pero se darán algunos ejemplos simples.

-- READ UNCOMMITTED/READ COMMITTED/REPEATABLE READ 利用主键进行等值查询
-- 对id=8的记录加S型Record Lock
select * from girl where id = 8 lock in share mode;

-- READ UNCOMMITTED/READ COMMITTED/REPEATABLE READ 利用主键进行等值查询
-- 对id=8的记录加X型Record Lock
select * from girl where id = 8 for update;

Bloqueo de espacio

Bloquea el espacio frente al registro y no permite insertar registros

MySQL puede resolver el problema de lectura fantasma a través de MVCC y bloqueo bajo el nivel de aislamiento de lectura repetible

Lectura actual: Lectura de
instantánea bloqueada: MVCC

Pero, ¿cómo bloquearlo? Debido a que estos registros fantasma no existen cuando se realiza la operación de lectura por primera vez, no tenemos forma de agregar Record Lock. En este momento, se puede resolver agregando Gap Lock, es decir, bloqueando el espacio.

inserte la descripción de la imagen aquí

Por ejemplo, si una transacción agrega un bloqueo de espacio al registro con id=8, significa que otras transacciones no pueden insertar nuevos registros en el espacio antes del registro con id=8, es decir, el registro con el valor de id. en el intervalo (5, 8) no está permitido Permite la inserción inmediata. Los registros con valores de identificación en el intervalo (5, 8) no se pueden enviar hasta que se confirme la transacción con el bloqueo de espacio

Veamos el siguiente proceso de bloqueo de SQL

-- REPEATABLE READ 利用主键进行等值查询
-- 但是主键值并不存在
-- 对id=8的聚集索引记录加Gap Lock
SELECT * FROM girl WHERE id = 7 LOCK IN SHARE MODE;

Dado que el registro con id=7 no existe, para evitar el fenómeno de lectura fantasma (para evitar el registro con id=7 en el conjunto de resultados obtenido al ejecutar la misma declaración bajo la misma transacción), debemos evitar otras transacciones de insertar el id antes de que se confirme la transacción actual = 7 registros, en este momento, puede agregar un Gap Lock a los registros con id = 8, es decir, otras transacciones no pueden insertar nuevos registros con valores de id en el intervalo (5, 8).

Déjame hacerte una pregunta, Gap Lock solo puede bloquear el espacio frente al registro, entonces, ¿cómo bloquear el espacio detrás del último registro?

De hecho, los datos mysql se almacenan en páginas, y cada página tiene 2 pseudo registros

  1. Registro mínimo, que representa el registro más pequeño de la página.
  2. registro upremum, que representa el registro más grande de la página

Para evitar que otras transacciones inserten registros cuyo valor de id esté en el rango de (12, +∞), podemos agregar un bloqueo de brecha al registro Supremum de la página donde se encuentra el registro id = 12. En este momento, se puede evitar que otras transacciones inserten el valor de id en (12), +∞) un nuevo registro para este intervalo

Bloqueo de tecla siguiente

Al mismo tiempo, bloquee los datos y el espacio frente a los datos, es decir, los datos y el espacio frente a los datos no pueden insertar registros
, para que pueda entender Siguiente-tecla Bloqueo = Registro Bloqueo + Espacio Cerrar con llave
inserte la descripción de la imagen aquí

-- REPEATABLE READ 利用主键进行范围查询
-- 对id=8的聚集索引记录加S型Record Lock
-- 对id>8的所有聚集索引记录加S型Next-key Lock(包括Supremum伪记录)
SELECT * FROM girl WHERE id >= 8 LOCK IN SHARE MODE;

Porque para resolver el problema de la lectura fantasma, es necesario prohibir que otras transacciones inserten registros con id>=8, por lo que

  • Agregue bloqueo de registro tipo S al registro de índice agrupado con id = 8
  • Agregar bloqueo de tecla siguiente tipo S a todos los registros de índice agrupados con id>8 (incluidos los pseudorregistros supremos)

Con el fin de darle una mejor comprensión

bloqueo de nivel de mesa

Los bloqueos de mesa también se dividen en bloqueos S y bloqueos X.

Al ejecutar instrucciones de selección, inserción, actualización y eliminación en una tabla, el motor de almacenamiento de innodb no agregará bloqueos S o bloqueos X a nivel de tabla a la tabla.

Cuando se ejecutan algunas declaraciones DDL como ALTER TABLE y DROP TABLE en una tabla, se agregarán bloqueos X a la tabla, por lo que otras transacciones se bloquearán al ejecutar declaraciones como SELECT INSERT UPDATE DELETE en esta tabla

Cuando la variable de sistema autocommit=0 e innodb_table_locks=1, para obtener manualmente el bloqueo S o el bloqueo X de la tabla t proporcionada por el motor de almacenamiento InnoDB, puede escribir esto

Agregue un bloqueo S de nivel de tabla a la tabla t

lock tables t read

Agregue un bloqueo X de nivel de tabla a la tabla t

lock tables t write

Si una transacción agrega un bloqueo S a una tabla, entonces

  • Otras transacciones pueden continuar adquiriendo el bloqueo S en la mesa
  • Otras transacciones pueden continuar adquiriendo bloqueos S en ciertos registros de la tabla
  • Otras transacciones no pueden continuar adquiriendo bloqueos X en la mesa
  • Otras transacciones no pueden continuar adquiriendo bloqueos X en algunos registros de la tabla

Si una transacción agrega bloqueos X a la tabla, entonces

  • Otras transacciones no pueden continuar adquiriendo el bloqueo S en la mesa
  • Otras transacciones no pueden continuar obteniendo bloqueos S para algunos registros en la tabla
  • Otras transacciones no pueden continuar adquiriendo bloqueos X en la mesa
  • Otras transacciones no pueden continuar adquiriendo bloqueos X en algunos registros de la tabla

Por lo tanto, debe tener cuidado al modificar tablas en línea, porque se bloquearán una gran cantidad de transacciones.En la actualidad, existen muchos métodos maduros para modificar tablas en línea, por lo que no los repetiré.

También hay bloqueos IS (bloqueos compartidos previstos) y bloqueos IX (bloqueos exclusivos previstos) a nivel de tabla.

Cuando una cosa pone un bloqueo S en un registro, también pone un bloqueo IS en la tabla correspondiente al registro (el bloqueo IS es un bloqueo a nivel de tabla).Cuando una cosa pone un bloqueo X en un registro, también pone un Bloqueo IX en la tabla correspondiente al registro (bloqueo IX). El bloqueo es un bloqueo a nivel de tabla)

Implementación del nivel de aislamiento de transacciones

RR RC
selección normal MVCC MVCC
Bloqueado seleccionar y actualizar
seleccionar... en modo nítido
seleccionar... para actualizar
insertar
borrar
actualizar
Bloqueo de registro Bloqueo de
espacio Bloqueo
de tecla siguiente
Bloqueo de registro
*

Blog de referencia

[1] https://souche.yuque.com/bggh1p/8961260/gyzlaf
[2] https://zhuanlan.zhihu.com/p/35477890
Clasificación de varios bloqueos
[3] https://www.hacker66.me /detalle/ZYXWPXH.html

Supongo que te gusta

Origin blog.csdn.net/zzti_erlie/article/details/123743716
Recomendado
Clasificación