该--single-transaction
的选项mysqldump
做一做FLUSH TABLES WITH READ LOCK
启动备份作业之前,但只在一定条件下。这些条件之一就是您还指定了--master-data
选项。
在源代码中,从mysql-5.6.19/client/mysqldump.c
5797行开始:
if ((opt_lock_all_tables || opt_master_data ||
(opt_single_transaction && flush_logs)) &&
do_flush_tables_read_lock(mysql))
goto err;
为了在开始可重复读取事务之前获得精确的binlog坐标的固定锁定,该--master-data
选项触发此锁定,以获取该锁定,然后在获得binlog坐标后释放该锁定。
实际上,请先mysqldump
执行a,FLUSH TABLES
然后再执行a ,这是FLUSH TABLES WITH READ LOCK
因为在初始刷新需要一些时间的情况下,两者都可以使读取锁定更快地获得。
...然而...
一旦它获得了binlog坐标,就mysqldump
发出一条UNLOCK TABLES
语句,这样就不会由于开始刷新而造成任何阻塞。任何线程都不应该Waiting for table flush
是由于mysqldump
保持事务而导致的。
当您看到处于该Waiting for table flush
状态的线程时,这应该意味着该FLUSH TABLES [WITH READ LOCK]
语句已发出,并且在查询启动时仍在运行 -因此,查询必须等待表刷新后才能执行。对于您已发布的流程列表,它mysqldump
是从同一张表中读取的,并且查询已经运行了一段时间,但是阻塞查询并没有这么长时间被阻塞。
这一切都表明发生了其他事情。
在Bug#44884中,存在一个长期存在的问题FLUSH TABLES
,即内部的工作方式。 如果问题仍然存在,我不会感到惊讶,如果这个问题曾经得到“解决” ,我会感到惊讶,因为这是一个非常复杂的问题需要解决-实际上在高并发环境中无法真正解决-以及任何尝试修复它可能会带来破坏其他事物或创建新的,不同的但仍不理想的行为的巨大风险。
看来这可能就是您所看到的解释。
特别:
如果您有一个针对表运行的长时间运行的查询FLUSH TABLES
,然后发出,则FLUSH TABLES
will会阻塞,直到长时间运行的查询完成。
此外,在FLUSH TABLES
发出之后开始的所有查询都将阻塞,直到FLUSH TABLES
完成为止。
此外,如果您取消了FLUSH TABLES
查询,被阻塞的查询仍将在原始的长期运行的查询(被阻塞的FLUSH TABLES
查询)上阻塞,因为即使被终止的查询FLUSH TABLES
没有完成,该表(那个或涉及长期运行查询的更多内容)仍在刷新过程中,并且只要长期运行查询完成,挂起的刷新将立即发生-但不是在此之前。
这里可能得出的结论是,另一个进程-可能是另一个mysqldump,一个不明智的查询或一个编写不当的监视进程试图刷新表。
该查询随后被未知机制杀死或超时,但是其后遗症一直持续到mysqldump
从相关表中读取完为止。
您可以通过尝试FLUSH TABLES
运行长时间运行的查询来复制此条件。然后开始另一个查询,这将阻止。然后终止FLUSH TABLES
查询,这不会取消阻止最新查询。然后终止第一个查询,或者让它完成,最后一个查询将成功运行。
事后考虑,这无关紧要:
Trx read view will not see trx with id >= 1252538405, sees < 1252538391
这是正常现象,因为mysqldump --single-transaction
发出START TRANSACTION WITH CONSISTENT SNAPSHOT
,会阻止它转储正在进行转储时更改的数据。--single-transaction
否则,开始时获得的二进制日志坐标将毫无意义,因为这将不是它声称的那样。这在任何意义上都不应与此Waiting for table flush
问题相关,因为此事务显然没有任何锁。