Caso de interbloqueo cuatro

Fuente: cuenta pública yangyidba

Un
punto muerto , prólogo , de hecho, es un problema técnico muy interesante también es muy desafiante, probablemente cada parte del desarrollo y los estudiantes de DBA se encontrarán en el curso de su trabajo. Con respecto al punto muerto, continuaré escribiendo una serie de estudios de casos, con la esperanza de ayudar a los amigos que quieran entender el punto muerto. Este artículo presenta un ejemplo de interbloqueo causado por tres insertos simultáneos. La causa principal es que la clave única del inserto se aplica al bloqueo GAP especial del bloqueo de intención de inserción. De hecho, es más razonable llamar a Insertar Intention Gap Lock.

2. Análisis de casos
2.1 Preparación del entorno 
Servidor Percona 5.6 Modo RR

  1. CREAR TABLA `t6` (

  2.   ʻId` int (11) NOT NULL AUTO_INCREMENT,

  3.   ʻA` int (11) DEFAULT NULL,

  4.   CLAVE PRIMARIA (ʻid`),

  5.   CLAVE única ʻidx_a` (ʻa`)

  6. ) MOTOR = InnoDB AUTO_INCREMENT = 1 JUEGO DE CARTAS POR DEFECTO = utf8mb4;

  7. insertar en los valores t6 (1,2), (2,8), (3,9), (4,11), (5,19)

sess1

sess2

sess3

empezar;



insertar en t6 (id, a) valores (6,15);

empezar;



insertar en t6 (id, a) valores (7,15);

empezar;



insertar en t6 (id, a) valores (8,15);

Retroceder; 


ERROR 1213 (40001): Se ha encontrado un interbloqueo al intentar obtener el bloqueo; intente reiniciar la transacción


2.2 Registro de interbloqueo

  1. ------------------------

  2. ÚLTIMO DEADLOCK DETECTADO

  3. ------------------------

  4. 2017-09-18 10:03:50 7f78eae30700

  5. *** (1) TRANSACCIÓN:

  6. TRANSACCIÓN 462308725, ACTIVO 18 segundos insertando, hilo declarado dentro de InnoDB 1

  7. tablas mysql en uso 1, bloqueadas 1

  8. LOCK WAIT 4 estructura (s) de bloqueo, tamaño de pila 1184, bloqueo (s) de 2 filas, deshacer entradas de registro 1

  9. Id. De subproceso de MySQL 3825465, identificador de subproceso del sistema operativo 0x7f78eaef4700, Id. De consulta 781148519 actualización de raíz localhost

  10. insertar en t6 (id, a) valores (7,15)

  11. *** (1) ESPERANDO A QUE SE OTORGUE ESTE BLOQUEO:

  12. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308725 lock_mode X insertar intención en espera

  13. *** (2) TRANSACCIÓN:

  14. TRANSACCIÓN 462308726, ACTIVO 10 segundos insertando, hilo declarado dentro de InnoDB 1

  15. tablas mysql en uso 1, bloqueadas 1

  16. 4 estructuras de bloqueo, tamaño de pila 1184, bloqueo (s) de 2 filas, deshacer entradas de registro 1

  17. Id. De subproceso de MySQL 3825581, identificador de subproceso del sistema operativo 0x7f78eae30700, Id. De consulta 781148528 actualización de raíz localhost

  18. insertar en t6 (id, a) valores (8,15)

  19. *** (2) SOSTIENE EL (LOS) BLOQUEO (S):

  20. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308726 modo de bloqueo S

  21. *** (2) ESPERANDO A QUE SE OTORGUE ESTE BLOQUEO:

  22. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308726 lock_mode X insertar intención en espera

  23. *** RETROCAMOS LA TRANSACCIÓN (2)

2.3 Análisis de interbloqueo En
primer lugar, aún necesitamos enfatizar nuevamente la lógica de bloqueo de la operación de inserción.

La primera etapa: verificación de restricción de unicidad, primero solicite LOCK_S + LOCK_ORDINARY.
Segunda etapa:  adquiera el bloqueo de la etapa uno e inserte correctamente, la posición de inserción tiene un bloqueo de espacio: LOCK_INSERT_INTENTION, para evitar otros conflictos de claves únicas de inserción.
Nueva inserción de datos: LOCK_X + LOCK_REC_NOT_GAP
Para la operación de inserción, si se produce un conflicto de restricción única, debe agregar S Bloqueo de tecla siguiente al índice único en conflicto. A partir de aquí, encontrará que incluso en el nivel de aislamiento de la transacción RC, también habrá un bloqueo de bloqueo de tecla siguiente, bloqueando así la concurrencia. Sin embargo, lo que el documento no explica es que para el índice único donde se detecta el conflicto, el hilo de espera necesita bloquear el siguiente registro después de obtener el Bloqueo S. El código fuente se juzga mediante la función row_ins_scan_sec_index_for_duplicate.

En segundo lugar, necesitamos la matriz de compatibilidad desbloqueada.

De la matriz de compatibilidad, podemos sacar las siguientes conclusiones:

  1. No habrá conflictos entre las operaciones INSERT.

  2. GAP, Next-Key bloqueará Insert.

  3. GAP y Record, Next-Key no entrarán en conflicto

  4. Grabar y grabar, la siguiente clave entra en conflicto entre sí.

  5. El bloqueo de inserción existente no impide que se agreguen bloqueos.

En este caso, se ejecutan tres sesiones al mismo tiempo, planeo analizar el registro de transacciones después de que cada paso se ejecuta paso a paso.

El primer paso, sess1 realiza la operación de inserción

insertar en t6 (id, a) valores (6,15);

  1. --- TRANSACCIÓN 462308737, ACTIVO 5 seg

  2. 1 estructura (s) de bloqueo, tamaño de pila 360, 0 bloqueo (s) de fila, deshacer entradas de registro 1

  3. Id. De subproceso de MySQL 3825779, identificador de subproceso del sistema operativo 0x7f78eacd9700, Id. De consulta 781149440 localhost root init

  4. mostrar el estado del innodb del motor

  5. TABLE LOCK table `test``t6` trx id 462308737 modo de bloqueo IX

Debido a la primera declaración insertada, la verificación de conflicto de unicidad pasó y la inserción fue exitosa (6,15). En este momento, la sesión sess1 mantiene el bloqueo LOCK_X | LOCK_REC_NOT_GAP de (6,15). Consulte "INSERT establece un bloqueo exclusivo en la fila insertada. Este bloqueo es un bloqueo de registro de índice, no un bloqueo de tecla siguiente (es decir, no hay bloqueo de espacio) y no evita que otras sesiones se inserten en el espacio antes de la fila insertada. "El

segundo paso, sess2 realiza una operación de
inserción inserta en los valores t6 (id, a) (7,15);

  1. --- TRANSACCIÓN 462308738, ACTIVO 4 seg insertando

  2. tablas mysql en uso 1, bloqueadas 1

  3. LOCK WAIT 2 estructura (s) de bloqueo, tamaño de pila 360, 1 bloqueo (s) de fila, deshacer entradas de registro 1

  4. Id. De subproceso de MySQL 3825768, identificador de subproceso del sistema operativo 0x7f78ea9c9700, Id. De consulta 781149521 actualización de raíz localhost

  5. insertar en t6 (id, a) valores (7,15)

  6. ------- TRX HA ESTADO ESPERANDO 4 SEGUNDOS PARA QUE SE OTORGUE ESTE BLOQUEO:

  7. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308738 modo de bloqueo S en espera

  8. ------------------

  9. TABLE LOCK table `test``t6` trx id 462308738 modo de bloqueo IX

  10. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308738 modo de bloqueo S en espera

  11. --- TRANSACCIÓN 462308737, ACTIVO 66 seg.

  12. 2 estructura (s) de bloqueo, tamaño de pila 360, 1 bloqueo (s) de fila, deshacer entradas de registro 1

  13. Id. De subproceso de MySQL 3825779, identificador de subproceso del sistema operativo 0x7f78eacd9700, Id. De consulta 781149526 localhost root init

  14. mostrar el estado del innodb del motor

  15. TABLE LOCK table `test``t6` trx id 462308737 modo de bloqueo IX

  16. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308737 lock_mode X bloquea rec pero no gap

Primero, la inserción de sess2 se aplica para un bloqueo IX, porque la sesión sess1 se ha insertado con éxito y mantiene el bloqueo de la fila X con la clave única a = 15, por lo que la inserción de sess2 realiza la verificación de unicidad, primero solicita LOCK_S + LOCK_ORDINARY y la lista de registro de transacciones solicita el modo de bloqueo S esperando


El tercer paso, sess3 realiza una operación de
inserción insertar en los valores t6 (id, a) (8,15);

  1. --- TRANSACCIÓN 462308739, ACTIVO 3 segundos insertando

  2. tablas mysql en uso 1, bloqueadas 1

  3. LOCK WAIT 2 estructura (s) de bloqueo, tamaño de pila 360, 1 bloqueo (s) de fila, deshacer entradas de registro 1

  4. Id. De subproceso de MySQL 3825764, identificador de subproceso del sistema operativo 0x7f78ea593700, Id. De consulta 781149555 actualización de raíz localhost

  5. insertar en t6 (id, a) valores (8,15)

  6. ------- TRX HA ESTADO ESPERANDO 3 SEGUNDOS PARA QUE SE OTORGUE ESTE BLOQUEO:

  7. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308739 modo de bloqueo S en espera

  8. ------------------

  9. TABLE LOCK table `test``t6` trx id 462308739 modo de bloqueo IX

  10. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308739 modo de bloqueo S en espera

  11. --- TRANSACCIÓN 462308738, ACTIVO 35 segundos insertando

  12. tablas mysql en uso 1, bloqueadas 1

  13. LOCK WAIT 2 estructura (s) de bloqueo, tamaño de pila 360, 1 bloqueo (s) de fila, deshacer entradas de registro 1

  14. Id. De subproceso de MySQL 3825768, identificador de subproceso del sistema operativo 0x7f78ea9c9700, Id. De consulta 781149521 actualización de raíz localhost

  15. insertar en t6 (id, a) valores (7,15)

  16. ------- TRX HA ESTADO ESPERANDO 35 SEGUNDOS PARA QUE SE OTORGUE ESTE BLOQUEO:

  17. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308738 modo de bloqueo S en espera

  18. ------------------

  19. TABLE LOCK table `test``t6` trx id 462308738 modo de bloqueo IX

  20. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308738 modo de bloqueo S en espera

  21. --- TRANSACCIÓN 462308737, ACTIVO 97 seg.

  22. 2 estructura (s) de bloqueo, tamaño de pila 360, 1 bloqueo (s) de fila, deshacer entradas de registro 1

  23. Id. De subproceso de MySQL 3825779, identificador de subproceso del sistema operativo 0x7f78eacd9700, Id. De consulta 781149560 localhost root init

  24. mostrar el estado del innodb del motor

  25. TABLE LOCK table `test``t6` trx id 462308737 modo de bloqueo IX

  26. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308737 lock_mode X bloquea rec pero no gap

Es consistente con el proceso de aplicación de bloqueo de la sesión sess2, todos los cuales están esperando que sess1 libere los recursos de bloqueo.

El cuarto paso sess1 realiza una operación de reversión, sess2 no confirma

sess1 rollback;
En este momento, sess2 se insertó correctamente y sess3 está en punto muerto. En este momento, el inserto de sess2 se insertó correctamente y aún no se ha enviado. La lista de transacciones es la siguiente:

  1. ------------

  2. ACTAS

  3. ------------

  4. Contador de id trx 462308744

  5. Purga realizada para trx sn: o <462308744 deshacer n: o <0 estado: en ejecución pero inactivo

  6. Longitud de la lista de historia 1866

  7. LISTA DE TRANSACCIONES PARA CADA SESIÓN:

  8. --- TRANSACCIÓN 462308737, no iniciada

  9. Id. De subproceso de MySQL 3825779, identificador de subproceso del sistema operativo 0x7f78eacd9700, Id. De consulta 781149626 localhost root init

  10. mostrar el estado del innodb del motor

  11. --- TRANSACCIÓN 462308739, no iniciada

  12. Id. De subproceso de MySQL 3825764, identificador de subproceso del sistema operativo 0x7f78ea593700, Id. De consulta 781149555 limpieza de raíz localhost

  13. --- TRANSACCIÓN 462308738, ACTIVO 75 seg.

  14. 5 estructura (s) de bloqueo, tamaño de pila 1184, bloqueo (s) de 3 filas, deshacer entradas de registro 1

  15. Id. De subproceso de MySQL 3825768, identificador de subproceso del sistema operativo 0x7f78eadce700, Id. De consulta 781149608 limpieza de raíz localhost

  16. TABLE LOCK table `test``t6` trx id 462308738 modo de bloqueo IX

  17. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308738 modo de bloqueo S

  18. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308738 modo de bloqueo S

  19. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` id trx 462308738 lock_mode X insertar intención

  20. RECORD LOCKS espacio id 227 página no 4 n bits 80 índice ʻidx_a` de la tabla `test``t6` trx id 462308738 modo de bloqueo S bloquea el espacio antes de la grabación

Tres, la causa del estancamiento

  • La inserción de sess1 es exitosa y se agrega un bloqueo X a la clave única de a = 15.

  • sess2 ejecuta insert (6,15) y realiza una verificación de unicidad antes de insertar. Se encuentra que la clave duplicada del registro insertado de sess1 necesita solicitar LOCK_S | LOCK_ORDINARY, pero entra en conflicto con sess1 (LOCK_X | LOCK_REC_NOT_GAP), únete a la cola de espera y espera a sess1 Suelte el candado.

  • sess3 ejecuta insert (7,15) y realiza una verificación de unicidad antes de insertar. Se encuentra que la clave duplicada con el registro insertado de sess1 necesita solicitar LOCK_S | LOCK_ORDINARY, pero entra en conflicto con sess1 (LOCK_X | LOCK_REC_NOT_GAP), únete a la cola de espera y espera a sess1 Suelte el candado.

  • sess1 ejecuta una reversión, sess1 libera el bloqueo de registro exclusivo (LOCK_X | LOCK_REC_NOT_GAP) en el índice a = 15, y luego sess2 y sess3 obtienen el bloqueo S (LOCK_S | LOCK_ORDINARY) con éxito, sess2 y sess3 solicitan el bloqueo de registro exclusivo en el índice a = 15 (LOCK_X | LOCK_REC_NOT_GAP), el registro solicita lock_mode X insertar la intención. Debido a que el bloqueo X y el bloqueo S son mutuamente excluyentes, tanto sess2 como sess3 esperan que el otro libere el bloqueo S, por lo que se produce un interbloqueo y MySQL elige deshacer uno de ellos.

Cuatro, resumen

El análisis de interbloqueo ya es muy desafiante, especialmente para insertar conflictos de claves únicas, que deben aplicarse en múltiples etapas y comprender la matriz de compatibilidad de los bloqueos. Para este conocimiento que necesito aprender y comprender, este artículo se puede considerar como una introducción. Si hay algún análisis y comprensión incorrectos, corríjame.

Lectura extendida

El texto completo ha terminado.

Disfruta MySQL :)



La clase "MySQL Core Optimization" de Teacher Ye se ha actualizado a MySQL 8.0, escanee el código para comenzar el viaje de la práctica de MySQL 8.0

Supongo que te gusta

Origin blog.csdn.net/n88Lpo/article/details/108459083
Recomendado
Clasificación