Si uso mysqldump --single-transaction, de acuerdo con los documentos, debería hacer tablas de descarga con bloqueo de lectura para obtener un estado coherente y luego comenzar una transacción y ningún escritor debería estar esperando.
Sin embargo, me he dado cuenta de la siguiente situación anoche:
Extracto de mostrar la lista de procesos completa:
cientos de esos ...
Command: Query
Time: 291
State: Waiting for table flush
Info: insert into db_external_notification.....
luego esto:
Command: Query
Time: 1204
State: Sending data
Info: SELECT /*!40001 SQL_NO_CACHE */ * FROM `db_external_notification`
y el resto de los hilos están en reposo
¿Alguien tiene alguna idea de qué están esperando estos insertos? No veo ninguna tabla FLUSH ni DDL ni nada mencionado en el manual que pueda hacer que las consultas esperen.
comando completo mysqldump
mysqldump --quick --add-drop-table --single-transaction --master-data=2 -uxx -pxx dbname
Supongo que aquí el rápido es redundante, probablemente un sobrante de épocas anteriores, este script es muy antiguo, pero no debería dañar nada
mysqldump
? En particular, ¿estás usando--flush-logs
o--master-data
...? Hay posibles interacciones entre las opciones.Respuestas:
La opción de transacción única de mysqldump no funciona
FLUSH TABLES WITH READ LOCK;
. Hace que mysqldump configure una transacción de lectura repetible para todas las tablas que se vuelcan.A partir de su pregunta, usted indicó que el SELECCIONAR mysqldump para la
db_external_notification
tabla está reteniendo cientos de comandos INSERT a esa misma tabla. Por qué está pasando esto ?Lo más probable es un bloqueo en el gen_clust_index (mejor conocido como el índice agrupado ). Este paradigma hace que coexistan páginas de datos e índices para una tabla. Esas páginas de índice se basan en la CLAVE PRIMARIA o en el índice RowID generado automáticamente (en el caso de que no haya una CLAVE PRIMARIA).
Debería poder detectar esto ejecutando
SHOW ENGINE INNODB STATUS\G
y buscando cualquier página de gen_clust_index que tenga un bloqueo exclusivo. Hacer INSERTs en una tabla con un índice agrupado requiere un bloqueo exclusivo para manejar el BTREE de PRIMARY KEY, así como la serialización del auto_increment.He discutido este fenómeno antes
Aug 08, 2011
: ¿Los bloqueos muertos de InnoDB son exclusivos de INSERT / UPDATE / DELETE?Dec 22, 2011
: Bloqueo de MySQL: ¿no se puede reiniciar normalmente?Dec 13, 2012
: MySQL InnoDB bloquea la clave principal al eliminar incluso en READ COMMITTEDACTUALIZACIÓN 2014-07-21 15:03 EDT
Mire las líneas 614-617 de su PastBin
Tenga en cuenta que la línea 617 dice
¿Qué me dice esto? Tiene una CLAVE PRIMARIA con un aumento automático activado
id
.Su máximo
id
para la tabladb_external_notification
fue menor que1252538391
cuando se lanzó mysqldump. Cuando resta1252538391
de1252538405
, esto significa que se han intentado 14 o más comandos INSERT. Internamente, esto necesitaría mover el auto_increment de esta tabla al menos 14 veces. Sin embargo, nada puede ser comprometido o incluso empujado al Log Buffer debido a la gestión de estaid
brecha.Ahora, mira la lista de procesos de tu PasteBin. A menos que haya contado mal, vi 38 DB Connections haciendo un INSERT (19 Antes del proceso mysqldump (identificación del proceso
6155315
), 19 Después). Estoy seguro de que 14 o más de esas conexiones están congeladas debido a la gestión de la brecha auto_increment.fuente
La
--single-transaction
opción demysqldump
hace hacerFLUSH TABLES WITH READ LOCK
antes de iniciar la tarea de respaldo , pero sólo bajo ciertas condiciones. Una de esas condiciones es cuando también especificas la--master-data
opción.En el código fuente, desde la
mysql-5.6.19/client/mysqldump.c
línea 5797:Para obtener un bloqueo sólido en las coordenadas precisas de binlog antes de comenzar la transacción de lectura repetible, la
--master-data
opción activa este bloqueo que se obtendrá y luego se liberará una vez que se hayan obtenido las coordenadas de binlog.De hecho,
mysqldump
hace unFLUSH TABLES
seguido por unFLUSH TABLES WITH READ LOCK
porque hacer ambas cosas permite que el bloqueo de lectura se obtenga más rápido en los casos en que el enjuague inicial toma algún tiempo....sin embargo...
Tan pronto como haya obtenido las coordenadas de binlog,
mysqldump
emite unaUNLOCK TABLES
declaración, por lo que no debería haber nada bloqueado como resultado del vaciado que inició. Tampoco debe haber ningún subprocesoWaiting for table flush
como resultado de la transacción que semysqldump
está reteniendo.Cuando vea un subproceso en el
Waiting for table flush
estado, eso debería significar que laFLUSH TABLES [WITH READ LOCK]
instrucción se emitió y aún se estaba ejecutando cuando se inició la consulta, por lo que la consulta debe esperar el vaciado de la tabla antes de que pueda ejecutarse. En el caso de la lista de procesos que ha publicado,mysqldump
está leyendo esta misma tabla, y la consulta se ha estado ejecutando durante un tiempo, sin embargo, las consultas de bloqueo no se han bloqueado durante tanto tiempo.Todo esto sugiere que algo más ha sucedido.
Hay un problema de larga data explicado en el Bug # 44884 con la forma en que
FLUSH TABLES
funciona internamente.No me sorprendería si el problema persiste,me sorprendería si este problema alguna vez se "soluciona" porque es un problema muy complejo de resolver, prácticamente imposible de solucionar en un entorno de alta concurrencia, y cualquier intento de arreglarlo conlleva un riesgo significativo de romper algo más, o crear un comportamiento nuevo, diferente y aún indeseable.Parece probable que esta sea la explicación de lo que estás viendo.
Específicamente:
si tiene una consulta de larga duración ejecutándose en una tabla y emite
FLUSH TABLES
,FLUSH TABLES
se bloqueará hasta que se complete la consulta de larga duración.además, cualquier consulta que comience después de que
FLUSH TABLES
se emita se bloqueará hasta queFLUSH TABLES
se complete.Además, si matas a la
FLUSH TABLES
consulta, las consultas que se están bloqueando aún bloquear en el original de consulta de larga duración, la que estaba bloqueando laFLUSH TABLES
consulta, porque a pesar de los muertosFLUSH TABLES
consulta no terminó, esa tabla (el uno, o más, involucrado con la consulta de larga duración) todavía está en proceso de ser vaciado, y ese vaciado pendiente va a suceder tan pronto como finalice la consulta de larga duración, pero no antes.La conclusión probable aquí es que otro proceso, tal vez otro mysqldump, o una consulta mal aconsejada, o un proceso de monitoreo mal escrito, intentó eliminar una tabla.
Esa consulta fue posteriormente eliminada o expirada por un mecanismo desconocido, pero sus efectos posteriores persistieron hasta que
mysqldump
terminó de leer la tabla en cuestión.Puede replicar esta condición intentando
FLUSH TABLES
mientras una consulta de larga duración está en proceso. Luego comience otra consulta, que bloqueará. Luego elimine laFLUSH TABLES
consulta, que no desbloqueará la última consulta. Luego elimine la primera consulta o deje que finalice, y la consulta final se ejecutará con éxito.Como una ocurrencia tardía, esto no está relacionado:
Eso es normal, porque
mysqldump --single-transaction
emite unSTART TRANSACTION WITH CONSISTENT SNAPSHOT
, que evita que arroje datos que se modificaron mientras el volcado estaba en progreso. Sin eso, las coordenadas de binlog obtenidas al principio no tendrían sentido, ya--single-transaction
que no serían lo que dicen ser. Esto no debería en ningún sentido estar relacionado con elWaiting for table flush
problema, ya que esta transacción obviamente no tiene bloqueos.fuente
Envié una solicitud de función: https://support.oracle.com/epmos/faces/BugDisplay?id=27103902 .
También escribí un parche contra 5.6.37 que usa el mismo método que - combinación única - combinación de datos maestro con - transacción única - datos esclavos, que se proporciona tal cual sin garantía. Úselo bajo su propio riesgo.
Lo probé con el siguiente proceso con esclavos a un maestro muy ocupado usando muchas tablas InnoDB con relaciones FK:
El proceso de envío de parches de Oracle es bastante intenso, por lo tanto, por qué tomé esta ruta. Puedo intentarlo con Percona y / o MariaDB para integrarlo.
fuente