pt-deadlock-logger默认单次扫描即退出,若INNODB STATUS中无当前死锁(需innodb_print_all_deadlocks=ON)则静默退出;必须用--interval或--run-time实现持续监控,否则无法捕获瞬态死锁。

pt-deadlock-logger 不是“开箱即用”的守护进程,它默认只跑一次就退出;生产环境必须配合 --run-time 或 --interval 才能持续捕获死锁。
为什么直接执行 pt-deadlock-logger 看不到死锁日志?
常见错误现象:运行 pt-deadlock-logger --user=root --socket=/var/run/mysqld/mysqld.sock 后命令立即返回、无输出,误以为工具失效。
根本原因在于:该工具默认行为是「单次扫描」——它只读取当前 SHOW ENGINE INNODB STATUS 输出中是否包含 “LATEST DETECTED DEADLOCK”,若没有,就静默退出。
- 死锁是瞬态事件,
INNODB STATUS仅保留最后一次死锁的完整上下文,且每 15 秒刷新一次;不持续轮询,大概率错过 -
--run-time 3600表示运行 1 小时后自动退出,适合临时诊断 -
--interval 30表示每 30 秒检查一次,这才是生产监控的正确姿势 - 必须确保 MySQL 已启用
innodb_print_all_deadlocks = ON(否则INNODB STATUS中不记录死锁)
如何把死锁日志写进数据库表而不是文件?
写入文件(如 --log /var/log/mysql/deadlocks.log)便于快速查看,但不利于聚合分析和告警;写入数据库表支持 SQL 查询、时间范围筛选、与业务日志关联,更适合生产。
关键步骤:
- 先在目标库(例如
monitoring)中创建表:CREATE TABLE deadlocks (server CHAR(20), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, thread INT UNSIGNED, txn_id BIGINT UNSIGNED, txn_time SMALLINT UNSIGNED, user CHAR(16), hostname CHAR(20), ip CHAR(15), db CHAR(64), tbl CHAR(64), idx CHAR(64), lock_type CHAR(16), lock_mode CHAR(1), wait_hold CHAR(1), victim TINYINT UNSIGNED, query TEXT, PRIMARY KEY(server,ts,thread)) ENGINE=InnoDB; - 使用
--dest指向该表:pt-deadlock-logger --dest h=localhost,D=monitoring,t=deadlocks --user=root --socket=/var/run/mysqld/mysqld.sock --interval 30 -
--dest的 DSN 格式必须完整,缺D=xxx(库名)或t=xxx(表名)会导致插入失败且无提示 - 注意权限:运行用户需对目标表有
INSERT权限,不一定要root,建议建专用账号
宝塔面板下部署时最常踩的三个坑
在宝塔环境中,MySQL socket 路径、错误日志位置、权限模型都与标准安装不同,以下三点极易出错:
-
--socket路径不是/tmp/mysql.sock,而是宝塔默认的/www/server/data/mysql.sock(可通过宝塔【数据库】→【配置修改】页底部看到) -
--log参数不能乱指:如果想用文件输出模式,路径必须指向可写目录(如/www/wwwlogs/deadlock.log),且宝塔默认禁止写入/var/log/下非白名单路径 - 宝塔的 MySQL 服务由面板管理,直接用
systemctl restart mysqld可能无效;修改my.cnf后,必须在宝塔界面点击【重启】按钮,否则innodb_print_all_deadlocks = ON不生效
死锁日志里哪些字段真正值得盯?
结构化日志入库后,不要只扫 query 字段。真正定位根因要看这三组字段组合:
-
victim = 1+wait_hold = 'w':说明该行记录的是被回滚事务的等待动作,它是“输家”,但它的 SQL 往往暴露了资源争抢模式 -
tbl和idx同时出现,比如tbl='orders'+idx='idx_user_status',说明冲突集中在某个二级索引上,可能暗示查询未走主键、或存在缺失索引 -
txn_time值很大(如 > 300),代表事务已持锁超 5 分钟,大概率是应用端未提交或异常 hang 住,不是典型并发死锁,而是长事务引发的连锁阻塞
死锁本身不可怕,可怕的是把它当成孤立事件处理;pt-deadlock-logger 输出的每一行,都是事务行为、SQL 写法、索引设计、应用逻辑四者共同作用的结果。漏掉 txn_time 或只看 query,等于只看了半张拼图。


















