FLUSH TABLES 会让所有查询排队等它,是因为它需关闭所有已打开表对象,但无法强制终止正持有表引用(如Sending to client、Copying to tmp table)的线程,导致后续访问该表的读写请求均卡在Waiting for table flush状态。

FLUSH TABLES 为什么会让所有查询排队等它
FLUSH TABLES 不是“清缓存”那么简单,它实际要关闭所有已打开的表对象。但 MySQL 无法强行关闭正在被查询、写入或传输结果的表——比如一个 SELECT 正卡在 Sending to client(客户端没及时收数据),或者一个大 JOIN 还在 Copying to tmp table,这些线程都还持着表的引用计数(share->ref_count)。只要有一个表没释放,FLUSH TABLES 就只能干等,而后续所有访问该表的语句(哪怕只是 SELECT)都会被堵在 Waiting for table flush 状态。
- 不是锁等待,是“关不掉表”的资源周转阻塞
- 影响范围不限于写操作:读请求也会被卡,只要它碰的是那个还没关掉的表
-
FLUSH TABLES t1同样会触发全表检查逻辑,不只是 t1;MySQL 要确保没有其他线程正用 t1 的旧版本 - 即使你 Ctrl+C 中断了
FLUSH TABLES命令,它的“等待状态”仍残留,直到原持有者退出
哪些线程最容易拖住 FLUSH TABLES
真正卡住 FLUSH TABLES 的,从来不是它自己,而是那些“看起来无害”的长生命周期线程:
-
Sending to client:客户端网络慢、应用没消费结果、或用 ORM 拉了 10 万行却只循环前 10 条——服务端 socket buffer 堆满后就卡在这儿 -
Sleep但Time> 300 秒:可能是连接池空闲连接未释放,也可能是测试脚本里写了SELECT SLEEP(3600) -
Locked或User lock:显式用了GET_LOCK()却忘了RELEASE_LOCK() -
Creating sort index/Converting HEAP to MyISAM:大结果集排序或隐式磁盘临时表,耗时远超预期
查法:SHOW PROCESSLIST,重点筛 State 非 Sleep 且 Time 明显偏高(比如 > 60)的线程,再看 Info 是否含全表扫描、无索引 JOIN、或 SLEEP。
备份脚本误用 FTWRL 是高频雷区
FLUSH TABLES WITH READ LOCK(FTWRL)比普通 FLUSH TABLES 更危险:它不仅要关表,还要抢两把全局 MDL 锁(读锁 + COMMIT 锁)。一旦遇到长查询,FTWRL 自身就会卡在 Waiting for table flush,而所有新来的 DML 全部排队等它——业务瞬间雪崩。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
mysqldump默认行为:如果没加--single-transaction,且库中存在 MyISAM 表,就会自动 fallback 到FTWRL -
--lock-all-tables和--single-transaction冲突:后者会被前者覆盖,等于白配 - RDS 用户注意:控制台一键备份若选“逻辑备份”,底层可能仍走
FTWRL,需确认是否支持--single-transaction模式 - 8.0+ 可用
LOCK TABLES FOR BACKUP替代,它不阻塞 InnoDB 读写,只拦 DDL
防范关键不在“怎么 flush”,而在“别让它等”
调大 table_open_cache 或 innodb_buffer_pool_instances 解决不了根本问题。真正有效的防范,是切断“长持有 → flush 卡死 → 全局排队”的链路:
- 应用层加查询超时:JDBC 设置
socketTimeout和queryTimeout,避免客户端挂起拖垮服务端 - DBA 巡检脚本必须包含:
SELECT * FROM information_schema.PROCESSLIST WHERE TIME > 300 AND COMMAND != 'Sleep'; - 禁止开发在生产环境直接执行
FLUSH TABLES类命令;运维操作走审批 + 自动化脚本(带KILL超时线程兜底) - 备份统一用
--single-transaction(InnoDB 专用)或存储层快照(LVM/EBS),彻底绕过表级 flush 逻辑
最常被忽略的一点:FLUSH TABLES 卡顿往往不是孤立事件,而是长查询、慢客户端、错误备份参数三者叠加的结果。定位时别只盯着 FLUSH 线程本身,先杀掉那个 Time 最大的非 Sleep 线程,通常一击即中。










