最可靠方式是查询information_schema.PROCESSLIST中STATE为'Waiting for global read lock'的线程;若返回非空,说明FTWRL已被持有,同时可结合performance_schema.global_status中Global_read_lock变量(8.0.26+)或SHOW OPEN TABLES WHERE In_use > 0等交叉验证。

如何确认当前 MySQL 是否被 FTWRL 持有全局读锁
FTWRL(FLUSH TABLES WITH READ LOCK)一旦执行,会阻塞所有写操作,并让后续的 DDL、DML 等写入语句无限期等待。但 MySQL 并不提供一个直接叫 is_ftwrl_active 的状态变量,得靠组合线索判断。
最可靠的方式是查 information_schema.PROCESSLIST 中是否存在状态为 Waiting for global read lock 的线程,同时结合 SHOW PROCESSLIST 和系统表交叉验证:
-
SELECT * FROM information_schema.PROCESSLIST WHERE STATE = 'Waiting for global read lock';—— 如果返回非空,说明已有线程被 FTWRL 阻塞,但注意:这不等于 FTWRL 正在执行中,而是“已被持有”后的表现 -
SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Global_read_lock';—— 该变量在 8.0.26+ 才存在,且仅当 FTWRL 持有时为ON;5.7 和早期 8.0 不支持,别白查 - 更通用的办法:执行
SHOW OPEN TABLES WHERE In_use > 0;,若结果为空且你确定有活跃写入连接,可能是 FTWRL 锁住了所有表的 flush 阶段,但这只是旁证,不能单独定论
为什么 mysqldump --single-transaction 不触发 FTWRL,而 --lock-all-tables 会
备份工具是否触发 FTWRL,取决于它显式调用的命令和选项。很多用户误以为 “用了 mysqldump 就一定安全”,其实关键在参数组合。
-
mysqldump --single-transaction依赖 InnoDB MVCC,只在开始时执行START TRANSACTION WITH CONSISTENT SNAPSHOT,全程不碰 FTWRL,对写入几乎无影响 -
mysqldump --lock-all-tables或未指定引擎时默认行为,会在 dump 前执行FLUSH TABLES WITH READ LOCK,这就是 FTWRL —— 它会立即阻塞所有 DML/DDL,直到 dump 结束或手动解锁 - Percona XtraBackup 在
--no-lock模式下也绕过 FTWRL;但加了--lock-ddl或运行在非 InnoDB 环境时,仍可能退化到 FTWRL - 某些旧版备份脚本或自研工具,会直接拼接
mysql -e "FLUSH TABLES WITH READ LOCK",这类调用不会留下明显标记,只能靠 processlist + 时间点日志回溯
FTWRL 持有期间哪些操作会被卡住,哪些还能跑
FTWRL 不是简单的“锁表”,而是进入一个全局只读临界区,影响范围比想象中更广。不是只有 INSERT/UPDATE 被堵,很多元数据操作也会 hang 住。
- 肯定被阻塞:
INSERT、UPDATE、DELETE、REPLACE、ALTER TABLE、DROP TABLE、CREATE INDEX - 容易被忽略但同样卡死:
TRUNCATE TABLE(本质是 DDL)、ANALYZE TABLE(需要获取 MDL 写锁)、任何尝试FLUSH LOGS或FLUSH ENGINE LOGS的操作 - 通常不受影响:
SELECT(纯读)、SHOW VARIABLES、SELECT FROM performance_schema.*(但部分表如events_statements_current可能延迟更新)、KILL命令本身(除非被 kill 的线程正持有锁) - 特别注意:
UNLOCK TABLES必须由执行 FTWRL 的同一个连接发出,其他连接发这个命令无效,也不会报错,只是静默忽略
如何快速定位是哪个备份进程在执行 FTWRL
FTWRL 是会话级命令,但它的效果是全局的,所以必须从连接源头追起。单纯看 PROCESSLIST 可能看不到“正在执行 FTWRL”的线程(因为它执行完就停在那等 unlock),得结合上下文线索。
- 先执行
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST ORDER BY TIME DESC LIMIT 10;,重点关注COMMAND = 'Sleep'且TIME特别长(比如 >300 秒)、STATE为空或'Waiting for table flush'的连接——这类往往是执行完 FTWRL 后没及时 unlock 的备份连接 - 检查该连接的
INFO字段是否为NULL(FTWRL 后通常清空了 last_query),再结合USER和HOST判断是否来自备份服务器 IP 或固定运维账号 - 翻查 MySQL 错误日志(
log_error对应路径)或 general_log(如果开启),搜索关键词FLUSH TABLES WITH READ LOCK,注意时间戳是否与阻塞发生时间吻合 - 终极手段:若允许短暂停服,可对疑似连接执行
KILL <id>;</id>—— 这会自动触发隐式UNLOCK TABLES,FTWRL 即刻释放(MySQL 5.7.19+ 和 8.0 默认行为)
FTWRL 的释放不依赖客户端主动调用 UNLOCK TABLES,只要那个连接断开(异常中断、超时、被 kill),MySQL 就会自动清理锁。但很多人忘了这点,盯着 “怎么 unlock” 想半天,其实 kill 掉源头连接最直接。











