深浅主题
锁等待超时
问题现象
出现 Lock wait timeout exceeded,更新卡住数十秒;CPU 不高,但接口线程和连接池逐渐耗尽。
适用环境
MySQL 8 InnoDB;需要 performance_schema 或 sys 视图读取权限。
本文是可复用的排障示例,不代表某次个人生产事故。命令中的名称、账号和数据均为示例,执行前请替换为已确认的目标。
复现或诊断步骤
- 在阻塞仍存在时查询 sys.innodb_lock_waits 或 performance_schema.data_lock_waits。
- 找到 blocking_pid、被阻塞 SQL、事务开始时间与持锁连接所属应用。
- 检查事务是否处于 idle in transaction 类状态:SQL 已结束但未提交;同时核查长批处理。
原因分析
锁被其他未结束事务持有,当前事务只能等待。默认配置下,锁等待超时通常回滚当前语句,不应假定整个事务已经干净结束;具体行为取决于 innodb_rollback_on_timeout。
修复示例
sql
SELECT waiting_pid, blocking_pid, wait_age,
locked_table, waiting_query, blocking_query
FROM sys.innodb_lock_waits;
SELECT trx_id, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;
SHOW VARIABLES LIKE 'innodb_rollback_on_timeout';应用捕获超时后明确回滚事务并返回可重试错误。与连接所属人员确认后优先让持锁事务正常提交或回滚;必须 KILL 时先确认连接身份及回滚影响,终止不是数据恢复手段。批任务分批提交前要评估部分完成的恢复方式。
验证方法
在测试环境持锁并触发超时,检查异常后连接归还、事务回滚与业务状态。解除阻塞后队列应下降;观察长事务是否再次出现。
常见误区
只调整等待时间会拖累连接池。不要把 sleeping 连接一律杀掉,其中可能存在未提交事务;也不要假定 KILL 后回滚立即完成。