应查 INFORMATION_SCHEMA.INNODB_TRX 筛选 TRX_STARTED 早于当前时间 1800 秒且 TRX_STATE = 'RUNNING'、TRX_ROWS_LOCKED > 0 的事务,优先用 KILL TRANSACTION TRX_ID 终止,避免误杀连接;MySQL 8.0+ 推荐结合 performance_schema.events_transactions_current 获取上下文;自动化推荐 pt-kill 并务必先 --print 预览。

直接查 INFORMATION_SCHEMA.INNODB_TRX,筛选 TRX_STARTED 早于当前时间 1800 秒的记录,再结合 TRX_STATE 和锁信息判断是否真需干预——不是所有“老”事务都危险,但 TRX_STATE = 'RUNNING' 且 TRX_ROWS_LOCKED > 0 的,基本就是问题源头。
怎么快速定位运行超 30 分钟的活跃事务
别依赖 SHOW PROCESSLIST,它只显示线程状态,不反映事务真实生命周期。必须查 INFORMATION_SCHEMA.INNODB_TRX,用时间差过滤:
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(TRX_STARTED) > 1800 ORDER BY TRX_STARTED;- 注意:
TRX_STATE = 'RUNNING'才代表事务仍在执行中;'LOCK WAIT'是被堵住,'ROLLING BACK'是已在回滚,这两类通常不用手动干预 - 如果返回为空,先确认账号是否有
PROCESS权限;再检查是否用了只读事务(如纯SELECT),这类事务默认不进该表 - MySQL 8.0+ 更推荐走
performance_schema.events_transactions_current关联sys.processlist,能直接看到current_statement,比INNODB_TRX多一层上下文
为什么不能直接 KILL CONNECTION_ID
一个连接(CONNECTION_ID)可能承载多个逻辑事务,尤其在连接池场景下。直接 KILL 123 会断开整个连接,导致应用重连、事务上下文丢失、甚至引发批量重试风暴。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 优先用
KILL TRANSACTION <code>TRX_ID(MySQL 5.7+ 支持),它只终止事务本身,连接保持复用 - 若版本是 5.6 或更老,只能退而求其次用
KILL QUERY <code>ID,但它只中断当前语句,事务仍为ACTIVE状态,必须额外补一句ROLLBACK,否则锁还在 - 杀之前务必先查
TRX_MYSQL_THREAD_ID,再KILL对应线程——避免误杀后台线程(如复制线程、event scheduler) -
KILL TRANSACTION不自动回滚,得靠脚本或人工在同连接里执行ROLLBACK,否则 undo log 持续膨胀
pt-kill 是唯一靠谱的自动化方案
手写定时脚本查 + KILL 容易出错:并发时查到的 TRX_ID 可能在 KILL 前已提交;权限失效后脚本静默失败;拼接 SQL 还有注入风险。
- 用
pt-kill --busy-time 1800 --kill --victims all --match-command Query --ignore-user system,它内置重试、连接复用、安全过滤 - 上线前必加
--print预览实际要杀哪些事务,别跳过这步 - 它默认不杀
SLEEP状态连接,但长事务常表现为Query(比如卡在UPDATE中间),所以--match-command Query是关键 - 注意
--victims all是批量杀,生产环境建议先用--victims oldest控制每次只杀最老的一个,降低冲击
回滚本身可能比事务还慢
别以为 KILL 后就万事大吉。如果事务已修改数百万行,回滚阶段会持续持有锁、消耗 IO、拖慢整个实例。这时候更稳妥的做法是:先查它是否还在真执行(比如看 INFO 字段是否有 SQL、TRX_ROWS_MODIFIED 是否增长),再决定是等它自然结束,还是硬杀。
真正容易被忽略的是 ORM 层静默失败:Django 的 @transaction.atomic 或 Spring 的 @Transactional 在异常未被捕获时,可能漏掉 ROLLBACK,留下“幽灵事务”。这类事务往往没有明显 SQL,INFO 为空,但 TRX_STATE = 'RUNNING' 且 TRX_ROWS_LOCKED 持续为 0——它只是卡在应用层没发 COMMIT/ROLLBACK 指令。

















