应直接查INFORMATION_SCHEMA.INNODB_TRX而非SHOW PROCESSLIST,因后者仅显示连接状态,无法反映事务真实运行状态,90%阻塞型长事务隐藏在Command='Sleep'、State=NULL但TRX_STATE='RUNNING'的“假空闲”连接中。

直接查 INFORMATION_SCHEMA.INNODB_TRX,别信 SHOW PROCESSLIST —— 它根本看不到事务级阻塞,容易漏掉真正卡住的 Sleep 连接。
为什么 SHOW PROCESSLIST 会漏掉阻塞源
很多“挂起”的长事务在 PROCESSLIST 里显示为 Command = 'Sleep'、State = NULL、Time 很大(比如 1800 秒),但 Info 为空。这类连接往往已执行 BEGIN 却没 COMMIT 或 ROLLBACK,事务锁从那一刻就持有了,而 PROCESSLIST 不反映事务级状态。
更关键的是:INFORMATION_SCHEMA.INNODB_TRX 才记录事务真实开始时间(TRX_STARTED)、状态(TRX_STATE)和对应线程 ID(TRX_MYSQL_THREAD_ID)。一个连接可能复用多次,PROCESSLIST.ID 和 INNODB_TRX.TRX_MYSQL_THREAD_ID 并不总一致;必须靠后者定位事务归属。
-
TRX_STATE = 'RUNNING'且TRX_STARTED时间远早于当前时间 → 高风险悬挂事务 -
TRX_WAITING_TRX_ID IS NOT NULL→ 正被其他事务堵着,得顺藤摸瓜查源头 -
TRX_ROWS_LOCKED > 1000或TRX_ROWS_MODIFIED > 0→ 已锁大量行或正在改数据,冲突概率陡增
怎么快速定位阻塞链:从 INNODB_LOCK_WAITS 入手
单看一个事务看不出全貌。真正能直观看到“谁在等谁”的是 INNODB_LOCK_WAITS:
WAITING_TRX_ID 对应被堵住的事务,BLOCKING_TRX_ID 对应持锁者,两字段直接构成锁等待链。
常用诊断 SQL:
SELECT r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS w
JOIN INFORMATION_SCHEMA.INNODB_TRX b ON b.trx_id = w.blocking_trx_id
JOIN INFORMATION_SCHEMA.INNODB_TRX r ON r.trx_id = w.requesting_trx_id;
输出中优先终止 waiting_thread(新请求),而不是 blocking_thread(持锁方)—— 前者对业务影响更小,且避免扩大阻塞面。
KILL TRANSACTION 还是 KILL CONNECTION?看版本和场景
MySQL 5.7+ 支持 KILL TRANSACTION <code>TRX_ID,它只终止事务本身,连接保持复用,适合连接池场景(如 HikariCP)。但注意:KILL TRANSACTION 不自动回滚,需人工或脚本在同连接里补一句 ROLLBACK,否则 undo log 持续膨胀、锁仍不释放。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
如果版本是 5.6 或更老,只能退而求其次用 KILL QUERY <code>ID,但它只中断当前语句,事务仍为 ACTIVE 状态,必须额外执行 ROLLBACK。
严禁直接 KILL CONNECTION <code>ID 处理 TRX_WAITING_TRX_ID IS NOT NULL 的等待方——这会让持锁者继续跑,堵得更死。
- 先查
TRX_MYSQL_THREAD_ID,再KILL→ 避免误杀后台线程(如复制线程、event scheduler) - 执行
KILL CONNECTION后,SHOW PROCESSLIST显示状态为Killed是正常现象,回滚在后台异步进行 - 云数据库(如阿里云 RDS)常屏蔽
PROCESSLIST全量视图,但INNODB_TRX一般仍可查(需SUPER或CONNECTION_ADMIN权限)
自动化处理务必先 --print 预览
手写定时脚本查 + KILL 容易出错:并发时查到的 TRX_ID 可能在 KILL 前已提交;权限失效后脚本静默失败;拼接 SQL 还有注入风险。
pt-kill 是唯一靠谱的自动化方案。它内置重试、连接复用、安全过滤,还能按匹配条件(如 user、db、state、time)精准筛选。
上线前务必加 --print 预览:
pt-kill --busy-time 60 --kill --victims all --match-command Query --ignore-user system --print
注意:--victims all 会杀所有匹配事务,而默认不杀 SLEEP 状态连接——但长事务常表现为 Query 或 Locked,所以要明确指定 --match-state。
复杂点在于:事务是否真该被杀,不能只看时长。很多业务逻辑依赖事务原子性(比如订单创建 + 库存扣减 + 日志写入),KILL 前必须确认上下文;TRX_QUERY 字段又常常为空,得靠 TRX_STARTED、TRX_WAITING_TRX_ID 和关联 PROCESSLIST 的 Info 综合判断。

















