不能只看show processlist中状态为sleep就跳过——真正持锁的事务可能处于trx_state='running'或'lock wait',须查innodb_trx定位并kill connection回滚;因show processlist仅反映连接命令状态,而innodb_trx记录事务级状态,未提交事务即使sql执行完仍持锁。

直接结论:不能只看 SHOW PROCESSLIST 里状态是 Sleep 就跳过——真正持锁的事务可能正卡在 TRX_STATE = 'RUNNING' 或 'LOCK WAIT',必须查 INNODB_TRX 定位,再用 KILL CONNECTION 强制回滚释放锁。
为什么 SHOW PROCESSLIST 找不到真凶?
常见错误现象:执行 SHOW PROCESSLIST 看到一堆 Command = Sleep 的连接,就认为“没活事务”,结果业务仍卡死。这是因为:
-
INNODB_TRX记录的是事务级状态,而SHOW PROCESSLIST只反映连接当前命令状态 - 一个已启动但未提交/回滚的事务,哪怕 SQL 已执行完,只要没
COMMIT或ROLLBACK,trx_state就仍是RUNNING,锁一直挂着 - 只读事务、
autocommit = 1的单条语句、或已提交但间隙锁未释放的事务,也不会出现在INNODB_TRX中
怎么准确定位长期持锁事务?
执行以下查询(需具备 PROCESS + SELECT 权限):
SELECT trx_id, trx_mysql_thread_id, trx_query, trx_state, trx_started, trx_rows_locked
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE trx_state IN ('RUNNING', 'LOCK WAIT')
AND trx_started
<p>重点关注:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2334" title="MySQL"><img
src="https://img.php.cn/upload/skill/000/000/081/178900927846657.jpg" alt="MySQL" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="overflowclass">MySQL</a>
<p class="overflowclass">编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。</p>
</div>
<a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
-
trx_query为空 → 事务卡在中间,没执行新语句但也没结束 -
trx_rows_locked > 1000→ 高风险,可能正在扫大范围数据 -
trx_started时间远超业务预期(生产建议阈值设为 30 秒,不是 10 分钟) -
trx_wait_started非空 → 正被其他事务堵着,得顺INNODB_LOCK_WAITS查源头
KILL CONNECTION 还是 KILL TRANSACTION?
MySQL 5.7+ 推荐优先用 KILL CONNECTION <code>thread_id(等价于旧版 KILL <code>thread_id),原因很实在:
-
KILL QUERY <code>thread_id只停当前语句,连接不断,事务不回滚,锁照常持有——对僵死连接完全无效 -
KILL TRANSACTION <code>trx_id能终止事务但保留连接,适合连接池场景;但它不会自动触发回滚,需确保后续有ROLLBACK或应用重连后清理 -
KILL CONNECTION会强制断连,InnoDB 必须执行完整回滚,锁才释放;执行后立刻查SHOW PROCESSLIST,ID 应消失;若状态变成Killed却卡住,说明正在回滚大事务,只能等 - 严禁对
User = 'system user'(如复制线程)或自己当前连接执行KILL
容易被忽略的三件事
执行 KILL CONNECTION 前,务必人工核对:
- 线程是否还在活跃:查
SHOW PROCESSLIST,确认State是Updating、Sending data或Locked,而非Sleep - SQL 是否可安全中断:比如百万行
UPDATE被杀,回滚本身要几十秒,期间锁仍占用;而ALTER TABLE被杀可能留下临时表 - 连接归属是否明确:检查
User和Host,排除备份工具(如mydumper)、监控连接或 DBA 手动诊断查询
自动脚本(如轮询 INNODB_TRX + KILL)极易误杀,且无法处理回滚中状态。真要自动化,请用 pt-kill --busy-time 30 --match-command Query --victims all --kill,并上线前先加 --print 预演。










