MyISAM 表不会发生死锁,所谓“卡住”实为表级写锁等待;应通过 SHOW PROCESSLIST 和 SHOW OPEN TABLES 定位持锁线程,谨慎 KILL 未完成的写操作线程,并最终迁移到 InnoDB 根治。

MyISAM 表根本不会发生死锁——所以你不需要、也不应该“杀掉死锁查询”。你看到的“卡住”是表级锁等待,不是死锁;强行按死锁思路 KILL 线程,既解决不了问题,还可能让正在执行的写操作中断,导致数据不一致或临时文件残留。
为什么 SHOW ENGINE INNODB STATUS 查不到 MyISAM 的“死锁”
因为该命令只输出 InnoDB 引擎的状态信息。MyISAM 没有事务、没有死锁检测器、也不维护锁队列。执行它,要么返回空,要么只显示无关的 InnoDB 日志片段。你试图从中找 LATEST DETECTED DEADLOCK,注定一无所获。
真正该查的是哪些线程在锁表
MyISAM 的阻塞只有一种来源:某个线程正持有整张表的写锁(WRITE),其他所有读写请求都排队等着。定位方式很直接:
- 运行
SHOW PROCESSLIST,重点关注State列为Locked或Waiting for table level lock的行 - 运行
SHOW OPEN TABLES WHERE In_use > 0,结果中In_use > 0表示该表当前被至少一个线程以写模式打开(即已加写锁) - 把两个结果对照:找出
Id相同且状态异常的线程,那就是锁源
安全终止阻塞线程的实操要点
确认目标线程后,用 KILL 是可行的,但必须满足以下条件才安全:
- 该线程执行的是纯写操作(如
INSERT、UPDATE、ALTER TABLE),且尚未完成——KILL 后 MyISAM 会丢弃未写入磁盘的部分,但不会损坏已有数据 - 避免 KILL 正在执行
LOAD DATA INFILE的线程,它可能已生成临时文件,KILL 后残留文件需手动清理(路径通常在/tmp/或datadir下,文件名含SQL_前缀) - 不要 KILL 处于
Sleep状态但持有表锁的连接(常见于未提交的显式LOCK TABLES ... WRITE),应先UNLOCK TABLES或确认应用逻辑是否遗漏了释放 - 执行
KILL <code>thread_id后,立刻再跑一次SHOW OPEN TABLES WHERE In_use > 0验证锁是否释放
最常被忽略的一点:MyISAM 锁等待无法通过调整隔离级别、索引或事务拆分来缓解——它的表级锁是引擎硬约束。杀线程只是应急,根治方式只有一条:把表迁到 InnoDB。否则每次大写入、DDL 或高峰读写争抢,你都会重复这套排查流程。


















