pt-deadlock-logger 查不到 lock wait timeout,因为它只捕获满足循环等待条件的死锁事件;而 lock wait timeout 是单向阻塞超时,innodb 不将其视为死锁,故不记录到 latest detected deadlock 段。

pt-deadlock-logger 本身不捕获 Lock wait timeout 错误,它只记录 MySQL 自动检测到的死锁事件;遇到 “Lock wait timeout exceeded” 报错,说明事务已超时被回滚,但未触发死锁检测——此时不能依赖 pt-deadlock-logger 查原因。
为什么 pt-deadlock-logger 查不到 Lock wait timeout
MySQL 的 innodb_lock_wait_timeout 是线性等待机制:事务 A 持有锁,事务 B 等待,B 超过设定秒数(默认 50 秒)后直接报错退出,整个过程没有循环等待,InnoDB 不认为这是死锁,因此不会写入死锁日志,pt-deadlock-logger 也就无从捕获。
- 死锁必须满足“循环等待”条件(A 等 B,B 等 A),由
innodb_deadlock_detect=ON自动识别并记录 -
Lock wait timeout是单向阻塞 + 超时,属于锁竞争严重或事务过长的表现,不是死锁 -
pt-deadlock-logger只轮询SHOW ENGINE INNODB STATUS中的LATEST DETECTED DEADLOCK段,该段对超时事件完全不输出
遇到 Lock wait timeout 应该查什么
重点转向实时锁状态和阻塞源头,而不是等死锁日志:
- 立刻执行
SELECT * FROM information_schema.INNODB_TRX\G,看哪些事务长时间运行、是否卡在UPDATE/DELETE上 - 关联
INNODB_LOCK_WAITS和PROCESSLIST找出谁在等谁:SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM information_schema.INNODB_LOCK_WAITS w INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id;
- 检查
SHOW FULL PROCESSLIST中状态为Locked或Waiting for table metadata lock的连接 - 确认慢查询日志是否开启,并过滤含
FOR UPDATE、SELECT ... LOCK IN SHARE MODE的语句:tail -f /www/server/data/mysql-slow.log | grep -i "for update\|lock in share"
pt-deadlock-logger 在这类场景中唯一有用的方式
它不能定位当前超时,但可辅助判断是否存在高频死锁干扰系统稳定性,间接放大锁等待压力:
- 确保已启用
innodb_print_all_deadlocks = ON,且log_error指向正确路径(如/var/log/mysql/error.log) - 用
pt-deadlock-logger定期采集结构化死锁记录,避免人工翻SHOW ENGINE INNODB STATUS:pt-deadlock-logger --socket=/var/run/mysqld/mysqld.sock --log=/var/log/mysql/deadlocks.log - 如果发现死锁频次高(比如每分钟多次),说明业务逻辑存在资源争抢模式(如无序更新多张表),这会加剧整体锁队列长度,使原本不会超时的操作因排队过久而超时
真正卡住你的,往往不是死锁本身,而是那个迟迟不提交的长事务——它像一根钉子,把后续所有请求都钉在了等待队列里。排查时别只盯着“deadlock”关键词,先找 trx_started 时间最早、trx_state 为 RUNNING 却没执行 SQL 的事务。











