lock_open全局锁会阻塞所有新查询执行,drop table操作被pthread_mutex_lock(&lock_open)包裹,导致新连接的select、insert、show tables等均卡在opening tables状态,qps断崖下跌且cpu使用率低。

LOCK_open 全局锁会阻塞所有新查询
执行 DROP TABLE 时,整个操作被 pthread_mutex_lock(&LOCK_open) 包裹。这个互斥锁控制 MySQL 打开/关闭表的入口,一旦持有,任何新连接尝试执行 SELECT、INSERT、甚至 SHOW TABLES 都会卡在 Opening tables 状态——不是慢,是直接排队等待。
常见现象:
-
SHOW PROCESSLIST中大量线程状态为Opening tables或Waiting for table metadata lock - QPS 断崖下跌,但 CPU 使用率可能很低
- 错误日志里没报错,监控却显示“无响应”
根本原因不是删文件本身慢,而是锁住的时间太长:Ext4 上删一个 10GB .ibd 文件可能耗时数秒;XFS 虽快些,但如果 Buffer Pool 有 5 万页要扫描,遍历 LRU 链表一样拖住 LOCK_open 不放。
Buffer Pool 扫描引发高 I/O 低 CPU 的假性“空转”
MySQL 5.7+ 不再同步刷脏页,但仍需从每个 Buffer Pool 实例的 LRU 和 flush list 中摘除该表所有缓存页。这不是顺序读,而是随机跳转查找——尤其 old sublist 页面稀疏,遍历时大量 cache miss + mutex 竞争,导致内核态等待加剧,表现为 I/O 等待飙升、CPU 却不上升。
确认是否真卡在这里:
- 查缓存页数量:
SELECT COUNT(*) FROM information_schema.INNODB_BUFFER_PAGE WHERE TABLE_NAME = 'db/tbl';—— 返回 >1000 就危险 - 看 InnoDB 状态:
SHOW ENGINE INNODB STATUS\G,翻到SEMAPHORES部分,盯buf_pool_mutex等待 - 检查 Buffer Pool 大小:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';—— 若超物理内存 70%,且表不大,大概率是它拖后腿
page_cleaner 超时是连锁反应的信号灯
DROP TABLE 还要清理自适应哈希索引(AHI),这会和 page_cleaner 线程争抢 dict_operation_lock。一旦卡住,page_cleaner loop 延迟超 4 秒,错误日志就会刷出:
page_cleaner: 1000ms intended loop took 24915ms. (flushed=182 and evicted=0, during the time.)
这不是孤立事件:
-
page_cleaner卡住 → flush list 积压 → 新写入被迫等待 → 更多线程堆积在LOCK_open - 临时缓解可关 AHI:
SET GLOBAL innodb_adaptive_hash_index = OFF;,但得评估对线上点查的影响 - 注意:MySQL 8.0 已优化 TRUNCATE 流程,但
DROP TABLE仍走老路径
硬链接方案能卸载 rm 的 IO 冲击,但不能跳过 DROP
只有 innodb_file_per_table = ON 才能用硬链接方案。它不减少 MySQL 内部动作,但把最伤 IO 的 unlink() 操作从 DROP 流程中剥离出去,交由 OS 异步完成。
四步实操(缺一不可):
- 确认独立表空间:
SELECT CREATE_OPTIONS FROM information_schema.TABLES WHERE TABLE_NAME = 't';,含ROW_FORMAT=COMPACT或FILE_PER_TABLE=1 - 冻结表状态:
FLUSH TABLES t FOR EXPORT;(确保.ibd一致) - Shell 创建硬链接:
ln /var/lib/mysql/db/t.ibd /tmp/t.ibd.hdlk(路径必须严格匹配) - 执行
DROP TABLE t;→ 此时只删元数据,.ibd因硬链接存在仍在磁盘上 - 后续异步
rm /tmp/t.ibd.hdlk,可用truncate -s 0分块清空,IO 完全可控
真正容易被忽略的是:硬链接只是转移了 IO 压力,LOCK_open 和 Buffer Pool 扫描依然发生——所以 FLUSH TABLES ... FOR EXPORT 必须做,否则 DROP 仍可能因脏页不一致而重试或卡死。











