当前位置: 代码网 > it编程>数据库>Mysql > MySQL事务阻塞卡死问题完整排查与解决流程

MySQL事务阻塞卡死问题完整排查与解决流程

2026年09月22日 Mysql 我要评论
引言在 mysql 日常运维、业务开发过程中,经常会遇到接口超时、sql 执行卡死、数据库锁等待、事务阻塞的问题。大多场景都是因为长事务、未提交事务、行锁竞争导致的事务阻塞。本文给大家分享一套从零排查

引言

在 mysql 日常运维、业务开发过程中,经常会遇到接口超时、sql 执行卡死、数据库锁等待、事务阻塞的问题。大多场景都是因为长事务、未提交事务、行锁竞争导致的事务阻塞。

本文给大家分享一套从零排查阻塞事务、定位阻塞sql、精准kill问题线程的完整实战流程,语句可直接复制复用,快速解决mysql锁等待、事务卡死问题。

一、问题场景概述

当出现以下现象时,基本可以判定是mysql事务阻塞导致:

  • 单条update/delete/insert语句长时间执行不结束
  • 业务接口请求超时、响应缓慢
  • 数据库cpu、内存无异常,但qps骤降
  • 频繁出现 lock wait timeout exceeded 锁等待超时报错

核心原因:一个事务持有行锁未提交,导致后续请求的事务阻塞等待,形成锁等待链路

二、完整排查解决流程

整套流程分为4个步骤:查询阻塞关系 → 根据线程pid查内核线程id → 定位阻塞源头sql → 杀死阻塞线程恢复服务

1. 查看所有被阻塞的事务与阻塞源头

通过 `innodb_lock_waits` 和 `innodb_trx` 系统表,直接查询出等待事务源头阻塞事务的对应关系,是排查锁阻塞的核心语句。

-- 查看事务阻塞关系:等待事务、阻塞事务、对应sql、线程id
select
    r.trx_id as waiting_trx_id,        -- 被阻塞的事务id
    r.trx_mysql_thread_id as waiting_thread,  -- 被阻塞的业务线程pid
    r.trx_query as waiting_query,      -- 被阻塞的sql语句
    b.trx_id as blocking_trx_id,       -- 阻塞别人的源头事务id
    b.trx_mysql_thread_id as blocking_thread, -- 阻塞源头线程pid
    b.trx_query as blocking_query      -- 造成阻塞的源头sql
from information_schema.innodb_lock_waits w
         inner join information_schema.innodb_trx b
                    on b.trx_id = w.blocking_trx_id
         inner join information_schema.innodb_trx r
                    on r.trx_id = w.requesting_trx_id;

字段说明

  • waiting_trx/waiting_thread/waiting_query:正在等待锁、被卡住的事务、线程、sql
  • blocking_trx/blocking_thread/blocking_query:持有锁、导致别人阻塞的源头事务、线程、sql

通过该语句可以直接定位到:到底是哪一条sql、哪一个线程卡住了整个业务

2. 根据业务线程pid查询内核线程id

通过第一步查询到的 `blocking_thread`(processlist_id),查询对应的数据库内核线程 thread_id,用于精准定位线程详情。

-- 根据业务线程pid查询内核线程id(替换为自己查询到的pid)
select thread_id
from performance_schema.threads
where processlist_id = 10146;

参数说明:将 `10146` 替换为第一步查到的 blocking_thread 阻塞线程id。

3. 查询阻塞线程正在执行的完整sql

通过上一步获取的 thread_id,查询线程当前正在执行的真实sql,确认阻塞源头业务语句。

-- 根据内核线程id,查询当前执行的sql语句
select thread_id, sql_text
from performance_schema.events_statements_current
where thread_id = 10146;

该语句可以精准拿到造成锁阻塞的原始sql,方便后续复盘优化(比如未加索引、长事务、事务未提交等问题)。

4. 杀死阻塞线程,恢复业务

确认阻塞线程和问题sql后,直接kill掉阻塞源头线程,释放锁,恢复正常业务访问。

-- 杀死阻塞线程(替换为第一步查询到的 blocking_thread 值)
kill xxx;

注意:kill 阻塞线程(blocking_thread),不要kill被阻塞的线程,kill源头才能彻底释放锁。

三、核心原理简单说明

  1. information_schema.innodb_trx:记录当前innodb所有运行中的事务信息,包含事务id、线程id、执行sql、事务状态
  2. information_schema.innodb_lock_waits:专门记录锁等待关系,是阻塞排查的核心视图
  3. performance_schema:性能监控库,可精准查询线程对应的真实执行sql

四、常见阻塞原因与优化方案

1. 事务执行时间过长(长事务)

业务代码中事务开启后,执行大量业务逻辑、网络请求,迟迟不commit,长期持有行锁。

优化:缩小事务范围,事务内只做数据库操作,避免事务嵌套业务逻辑。

2. 更新/删除语句无索引

where条件无索引,导致行锁升级为表锁,阻塞全表所有读写操作。

优化:保证update/delete语句where字段建立索引。

3. 程序异常导致事务未提交

代码报错、接口中断,导致事务未执行commit/rollback,线程挂起持有锁。

优化:全局异常捕获,确保事务最终一定会提交或回滚。

五、排查总结(速查清单)

  1. 执行阻塞查询sql,找到 blocking_thread 阻塞源头线程
  2. 通过pid查询内核线程id,核对阻塞sql
  3. 确认无误后 kill 阻塞线程,快速恢复业务
  4. 根据阻塞sql复盘代码,解决长事务、无索引、事务未提交问题

六、补充:日常预防建议

  • 禁止大事务、长事务,单事务执行时间控制在毫秒/秒级
  • 所有更新语句必须走索引,避免行锁变表锁
  • 开启mysql慢查询日志,监控超时sql
  • 定时巡检数据库长事务,提前规避阻塞问题

以上就是mysql事务阻塞卡死问题完整排查与解决流程的详细内容,更多关于mysql事务阻塞卡死问题的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com