mysqldumpslow无法识别myisam表锁问题,因其仅统计sql执行时间与频次,不记录锁等待上下文;myisam表锁阻塞表现为state=‘waiting for table level lock’且query_time未超阈值,需结合show processlist实时快照与慢日志时间戳对齐分析。

为什么mysqldumpslow看不出MyISAM表锁问题
因为mysqldumpslow只解析SQL语句耗时和出现频次,不记录锁等待上下文。MyISAM的表级锁阻塞不会体现为单条SQL执行时间变长,而是表现为:多个查询在State字段卡在Waiting for table level lock,但慢日志里它们的Query_time可能远低于慢查询阈值(比如0.1s),根本不会被记录。
真正要定位,得结合SHOW PROCESSLIST实时快照 + 慢日志时间戳对齐,而不是只盯mysqldumpslow输出。
如何从SHOW PROCESSLIST识别MyISAM锁等待
运行SHOW FULL PROCESSLIST,重点看State列和Time列:
-
State = 'Waiting for table level lock':明确是MyISAM表锁阻塞,不是InnoDB行锁 -
Time值持续增长(比如从2秒涨到15秒):说明该线程已在锁队列中等待很久 - 对应
Info里的SQL如果是SELECT,大概率被一个未提交的INSERT/UPDATE/DELETE或ALTER TABLE堵住 - 注意区分
'Locked'(旧版MySQL显示)和'Waiting for table level lock'(5.5+),两者等价
慢日志里怎么关联到具体被锁的MyISAM表
MySQL慢日志本身不记录锁对象,但你可以通过时间窗口反向排查:
- 记下慢日志中某条“看似不慢却实际卡住”的SQL的时间戳(如
# Time: 2024-04-10T08:23:41) - 立刻查该时刻前后的
SHOW PROCESSLIST输出(建议用脚本每5秒自动抓一次并打时间戳) - 过滤出
State LIKE '%table level lock%'且Time > 2的记录,看Info里涉及哪些表 - 检查这些表是否为MyISAM:
SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA='db_name' AND TABLE_NAME='tbl_name';
常见陷阱:误把FLUSH TABLES WITH READ LOCK导致的全局阻塞当成单表锁——它会让所有写操作卡在Waiting for global read lock,状态不同,需单独识别。
为什么myisam_recover_options开启后反而加剧锁延迟
当配置了myisam_recover_options=BACKUP,FORCE,MySQL会在打开损坏的MyISAM表时自动执行修复,而修复过程会加独占表锁,且不可中断。如果某张大表索引损坏,每次有查询命中它,都会触发修复 → 长时间独占锁 → 后续所有查询排队等锁。
- 现象:慢日志里没多少慢SQL,但
SHOW PROCESSLIST里大量Waiting for table level lock集中在同一张表 - 验证方式:
mysqlcheck --check --databases db_name看是否有error或repair提示 - 临时缓解:停掉应用,手动
REPAIR TABLE tbl_name,再关闭myisam_recover_options重启
MyISAM锁问题从来不在SQL写法,而在表状态、修复行为和并发模型本身。一旦发现锁等待集中在某几张表,优先检查它们是否损坏、是否被ALTER或OPTIMIZE长期持有锁,而不是优化WHERE条件。











