Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL事务阻塞卡死问题

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

作者:爱码猿

在 MySQL 日常运维、业务开发过程中,经常会遇到接口超时、SQL 执行卡死、数据库锁等待、事务阻塞的问题,大多场景都是因为长事务、未提交事务、行锁竞争导致的事务阻塞,本文给大家分享一套从零排查阻塞事务、定位阻塞SQL、精准kill问题线程的完整实战流程

引言

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

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

一、问题场景概述

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

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

二、完整排查解决流程

整套流程分为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;

字段说明

通过该语句可以直接定位到:到底是哪一条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事务阻塞卡死问题完整排查与解决流程的详细内容,更多关于MySQL事务阻塞卡死问题的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文