Significado de "bloquea rec, pero no espera en vacío" en el informe de punto muerto

12
  1. Sobre el significado de locks rec but not gap waitingen TRANSACTION (1), ¿cuál es el correcto?

    • ¿Ya se le otorgó el bloqueo de espacio, esperando el bloqueo agrupado de índice X?
    • ¿Ya se le otorgó el bloqueo agrupado de índice X, esperando el bloqueo de espacio?
  2. Hay 31 filas en la transacción (1). ¿Cuál es el significado de esas filas? ¿Esto representa un bloqueo de espacio?

     0: len 4; hex 800c20d6; asc     ;;
     ....
     29: SQL NULL;
     30: SQL NULL;
    

ÚLTIMO DETECTADO DEADLOCK Informe

    LATEST DETECTED DEADLOCK
    ------------------------
    2015-09-25 15:27:24 1b8084000


    *** (1) TRANSACTION:
    TRANSACTION 5226928, ACTIVE 0 sec fetching rows
    mysql tables in use 1, locked 1
    LOCK WAIT 31 lock struct(s), heap size 6544, 548 row lock(s)
    MySQL thread id 71, OS thread handle 0x1b45be000, query id 4085356 localhost root Creating sort index
    SELECT  `rpush_notifications`.* FROM `rpush_notifications`  WHERE (processing = 0 AND delivered = 0 AND failed = 0 AND (deliver_after IS NULL OR deliver_after < '2015-09-25 07:27:24'))  ORDER BY created_at ASC LIMIT 100 FOR UPDATE


    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 10287 page no 10901 n bits 152 index `PRIMARY` of table `ct_development`.`rpush_notifications` trx id 5226928 lock_mode X locks rec but not gap waiting
    Record lock, heap no 78 PHYSICAL RECORD: n_fields 31; compact format; info bits 0
     0: len 4; hex 800c20d6; asc     ;;
     1: len 6; hex 0000004fc1aa; asc    O  ;;
     2: len 7; hex 4c0000027b07fe; asc L   {  ;;
     3: len 30; hex 52707573683a3a436c69656e743a3a4163746976655265636f72643a3a41; asc Rpush::Client::ActiveRecord::A; (total 47 bytes);
     4: SQL NULL;
     5: len 30; hex 373838653836643365666465626262626639633464363261626433366132; asc 788e86d3efdebbbbf9c4d62abd36a2; (total 64 bytes);
     6: len 7; hex 64656661756c74; asc default;;
     7: len 7; hex 6869206d6f6d21; asc hi mom!;;
     8: len 13; hex 7b22666f6f223a22626172227d; asc {"foo":"bar"};;
     9: len 4; hex 80015180; asc   Q ;;
     10: len 1; hex 80; asc  ;;
     11: SQL NULL;
     12: len 1; hex 81; asc  ;;
     13: len 5; hex 99973276d8; asc   2v ;;
     14: SQL NULL;
     15: len 0; hex ; asc ;;
     16: SQL NULL;
     17: len 5; hex 99973276d6; asc   2v ;;
     18: len 5; hex 99973276d6; asc   2v ;;
     19: len 1; hex 80; asc  ;;
     20: SQL NULL;
     21: len 1; hex 80; asc  ;;
     22: SQL NULL;
     23: len 4; hex 80000002; asc     ;;
     24: len 4; hex 80000000; asc     ;;
     25: SQL NULL;
     26: SQL NULL;
     27: len 1; hex 80; asc  ;;
     28: SQL NULL;
     29: SQL NULL;
     30: SQL NULL;

    *** (2) TRANSACTION:

    TRANSACTION 5226922, ACTIVE 0 sec updating or deleting, thread declared inside InnoDB 0
    mysql tables in use 1, locked 1
    3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 1
    MySQL thread id 1446, OS thread handle 0x1b8084000, query id 4085345 localhost root updating
    UPDATE `rpush_notifications` SET processing = 0, delivered = 0, delivered_at = NULL, failed = 1, failed_at = '2015-09-25 07:27:24', error_code = NULL, error_description = '' WHERE `rpush_notifications`.`id` IN (794838, 794839)


    *** (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 10287 page no 10901 n bits 152 index `PRIMARY` of table `ct_development`.`rpush_notifications` trx id 5226922 lock_mode X locks rec but not gap
    Record lock, heap no 78 PHYSICAL RECORD: n_fields 31; compact format; info bits 0
     0: len 4; hex 800c20d6; asc     ;;
     1: len 6; hex 0000004fc1aa; asc    O  ;;
     2: len 7; hex 4c0000027b07fe; asc L   {  ;;
     3: len 30; hex 52707573683a3a436c69656e743a3a4163746976655265636f72643a3a41; asc Rpush::Client::ActiveRecord::A; (total 47 bytes);
     4: SQL NULL;
     5: len 30; hex 373838653836643365666465626262626639633464363261626433366132; asc 788e86d3efdebbbbf9c4d62abd36a2; (total 64 bytes);
     6: len 7; hex 64656661756c74; asc default;;
     7: len 7; hex 6869206d6f6d21; asc hi mom!;;
     8: len 13; hex 7b22666f6f223a22626172227d; asc {"foo":"bar"};;
     9: len 4; hex 80015180; asc   Q ;;
     10: len 1; hex 80; asc  ;;
     11: SQL NULL;
     12: len 1; hex 81; asc  ;;
     13: len 5; hex 99973276d8; asc   2v ;;
     14: SQL NULL;
     15: len 0; hex ; asc ;;
     16: SQL NULL;
     17: len 5; hex 99973276d6; asc   2v ;;
     18: len 5; hex 99973276d6; asc   2v ;;
     19: len 1; hex 80; asc  ;;
     20: SQL NULL;
     21: len 1; hex 80; asc  ;;
     22: SQL NULL;
     23: len 4; hex 80000002; asc     ;;
     24: len 4; hex 80000000; asc     ;;
     25: SQL NULL;
     26: SQL NULL;
     27: len 1; hex 80; asc  ;;
     28: SQL NULL;
     29: SQL NULL;
     30: SQL NULL;

    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 10287 page no 7992 n bits 1480 index `index_rpush_notifications_multi` of table `ct_development`.`rpush_notifications` trx id 5226922 lock_mode X locks rec but not gap waiting
    Record lock, heap no 1279 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
     0: len 1; hex 80; asc  ;;
     1: len 1; hex 80; asc  ;;
     2: len 4; hex 800c20d6; asc     ;;

    *** WE ROLL BACK TRANSACTION (2)

Esquema de tabla

CREATE TABLE `rpush_notifications` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(255) NOT NULL,
  `badge` int(11) DEFAULT NULL,
  `device_token` varchar(64) DEFAULT NULL,
  `sound` varchar(255) DEFAULT 'default',
  `alert` varchar(255) DEFAULT NULL,
  `data` text,
  `expiry` int(11) DEFAULT '86400',
  `delivered` tinyint(1) NOT NULL DEFAULT '0',
  `delivered_at` datetime DEFAULT NULL,
  `failed` tinyint(1) NOT NULL DEFAULT '0',
  `failed_at` datetime DEFAULT NULL,
  `error_code` int(11) DEFAULT NULL,
  `error_description` text,
  `deliver_after` datetime DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `alert_is_json` tinyint(1) DEFAULT '0',
  `collapse_key` varchar(255) DEFAULT NULL,
  `delay_while_idle` tinyint(1) NOT NULL DEFAULT '0',
  `registration_ids` mediumtext,
  `app_id` int(11) NOT NULL,
  `retries` int(11) DEFAULT '0',
  `uri` varchar(255) DEFAULT NULL,
  `fail_after` datetime DEFAULT NULL,
  `processing` tinyint(1) NOT NULL DEFAULT '0',
  `priority` int(11) DEFAULT NULL,
  `url_args` text,
  `category` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_rapns_notifications_multi` (`app_id`,`delivered`,`failed`,`deliver_after`),
  KEY `index_rpush_notifications_multi` (`delivered`,`failed`)
) ENGINE=InnoDB AUTO_INCREMENT=337371 DEFAULT CHARSET=utf8;
Ryan Lv
fuente

Respuestas:

20

Pregunta 1: InnoDB está tratando de obtener un bloqueo exclusivo en la fila (en realidad es un bloqueo en el registro de índice agrupado, el PK), pero no el espacio circundante (un bloqueo de espacio). Puede leer más sobre los bloqueos de registros y brechas aquí: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-record-locks

La solicitud de bloqueo exclusivo proviene de la cláusula "para actualización" agregada a la instrucción SELECT. Tenga en cuenta que al usar el nivel de aislamiento de lectura repetible (seleccione @@ session.tx_isolation), que es el valor predeterminado, el bloqueo exclusivo se colocará en cada fila examinada para SELECT, no solo las que se devuelven (las que coinciden todos los predicados en la cláusula WHERE). Por lo tanto, es posible que pueda reducir el número de filas examinadas y, por lo tanto, los bloqueos mantenidos, lo que reducirá en gran medida las posibilidades de conflictos, mediante el uso de un índice compuesto en: procesamiento, entregado, fallido, entregar_ después

No sé cuál es la cardinalidad (número de valores únicos) para esas columnas, pero generalmente debe enumerarlas en el índice compuesto desde la cardinalidad más alta hasta la más baja.

 

Pregunta 2: 31 es el número de campos en el registro de índice (o fila, lógicamente) que está intentando / esperando para obtener un bloqueo exclusivo. InnoDB usa una PK agrupada, por lo que los registros en el índice agrupado (la PK) contienen los campos para cada columna definida por el usuario - 29 campos en el caso de su tabla push_notifications: id ... categoría - y siempre hay dos adicionales campos internos para cada tabla InnoDB: un campo de ID de transacción de 6 bytes y un campo de puntero de desplazamiento de 7 bytes (se usan para MVCC). Entonces, los 31 elementos que ve en la lista son los campos contenidos en el registro de índice (o la fila, lógicamente) en los que estamos esperando el bloqueo.

 

Solo para su información: puede obtener más desgloses de los bloqueos de InnoDB utilizando nuevas tablas Information_Schema en 5.6+: https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-transactions.html

También hay algunos informes excelentes en el nuevo esquema SYS, que se incluye con el servidor en MySQL 5.7+ (aunque todavía no ha llegado al manual en línea): https://github.com/MarkLeith/mysql-sys # innodb_lock_waits - xinnodb_lock_waits

Puede instalar el último esquema SYS en MySQL 5.6 manualmente, si le interesa: https://github.com/MarkLeith/mysql-sys/blob/master/sys_56.sql

Para obtener más información al respecto: http://www.slideshare.net/Leithal/performance-schema-and-sys-schema-in-mysql-57

 

¡Espero que esto ayude!

Matt Lord
fuente