锁等待时间过长本质是事务长时间持锁或阻塞链路未释放,需从“谁在等、谁在占、为什么不放”三层排查:先用系统视图定位活跃阻塞源头,再分析sql执行逻辑与事务行为,最后结合日志监控追溯根因。

锁等待时间过长,本质是事务长时间持有锁或阻塞链路未及时释放,排查需从“谁在等、谁在占、为什么不放”三层切入,优先定位活跃阻塞源头,再分析事务行为与SQL执行逻辑。
查当前锁等待和阻塞关系
用系统视图快速识别“谁在等、被谁堵”:
- MySQL:查询 performance_schema.data_lock_waits(8.0+)或结合 information_schema.INNODB_TRX、INNODB_LOCKS(5.7)、INNODB_LOCK_WAITS 关联分析;常用语句:
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM information_schema.INNODB_TRX r INNER JOIN information_schema.INNODB_LOCK_WAITS w ON r.trx_id = w.requesting_trx_id INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id; - PostgreSQL:查 pg_stat_activity 和 pg_locks,重点关注 wait_event_type = 'Lock' 及 blocking_pid 字段;常用语句:
SELECT blocked.pid AS blocked_pid, blocked.usename AS blocked_user, blocking.pid AS blocking_pid, blocking.usename AS blocking_user, blocked.query AS blocked_query, blocking.query AS current_statement_in_blocking_process FROM pg_stat_activity blocked JOIN pg_stat_activity blocking ON blocking.pid = blocked.pid; -- 实际需关联 pg_locks 获取精确锁类型 - 注意过滤掉已结束或空闲事务(如 state = 'idle in transaction' 的长事务常是元凶)
看被阻塞事务的SQL与执行计划
拿到 waiting_query 或 blocked.query 后,不要只盯语句本身,重点检查:
- 是否缺少索引导致扫描全表?用 EXPLAIN ANALYZE 确认实际扫描行数与预估是否严重偏离
- 是否含 FOR UPDATE / LOCK IN SHARE MODE 且作用范围过大(如无 WHERE 条件或条件未命中索引)
- 是否在事务中混入了慢查询、网络调用、循环处理等非SQL操作,拉长事务生命周期
- 是否使用了 REPEATABLE READ 隔离级别却执行了范围锁(如 WHERE id > 100),易引发间隙锁等待
查持锁事务的行为与状态
对 blocking_trx_id 或 blocking_pid 进一步深挖:
- 查该会话的完整事务信息:trx_started 时间是否异常久?trx_state 是否为 'RUNNING' 但实际卡住?
- 查其当前执行语句(trx_query)是否正在做耗时操作(如大字段更新、子查询嵌套深、临时表排序)
- 确认应用层是否未正确提交/回滚(例如异常后忘记 rollback,或连接池配置不当导致连接复用但事务未清理)
- 检查是否有显式 START TRANSACTION 后未配对 COMMIT/ROLLBACK,尤其在存储过程或客户端手动事务中
辅助定位:日志与监控线索
单靠实时视图可能遗漏历史快照,需结合:
- 数据库慢查询日志(slow_query_log),筛选执行时间长且含 UPDATE/DELETE/SELECT ... FOR UPDATE 的语句
- 应用层日志,搜索 “timeout”、“lock wait”、“deadlock detected” 等关键词,反向定位触发SQL和业务场景
- 监控指标:持续观察 Innodb_row_lock_time_avg(MySQL)或 pg_stat_database.deadlocks(PG)突增,配合应用错误率判断影响面
- 若频繁发生,开启 innodb_print_all_deadlocks=ON(MySQL)或 log_lock_waits = on(PG),捕获完整锁冲突上下文










