news 2026/5/13 2:23:27

僵尸事务阻塞生产库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
僵尸事务阻塞生产库

僵尸事务阻塞生产库:数据库写操作全部卡死的排查与处理

背景

某天下午三点,监控突然告警:API 响应时间从正常的 50ms 飙升到 30 秒,大量请求超时。

查看应用日志,报错集中在数据库写操作:

PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

读操作还算正常,所有涉及写入的接口全部超时。

第一步:确认是锁等待问题

-- 查看当前等待锁的事务SELECT*FROMinformation_schema.INNODB_LOCK_WAITS;

输出一大堆记录,几十个事务都在等锁,而且等待时间都超过了 50 秒。

锁等待是症状,持锁不放的事务才是根源。

第二步:找出僵尸事务

-- 查看当前所有活跃事务,按运行时长倒序SELECTtrx_id,trx_state,trx_started,TIMESTAMPDIFF(SECOND,trx_started,NOW())AStrx_duration_sec,trx_rows_locked,trx_rows_modified,trx_queryFROMinformation_schema.INNODB_TRXORDERBYtrx_startedASC;

结果一目了然:

trx_id: 88888 trx_state: RUNNING trx_started: 2024-03-15 13:01:23 trx_duration_sec: 7156 ← 已经跑了将近 2 小时! trx_rows_locked: 48392 ← 持有将近 5 万个行锁 trx_rows_modified: 0 trx_query: NULL ← 当前没有在执行任何 SQL

找到了:一个事务开启了将近两个小时,持有大量行锁,但当前没有在执行任何 SQL(trx_query = NULL)。这就是典型的僵尸事务——事务开启后由于某种原因(程序异常、连接假死、忘记提交)卡在那里,一直占着锁不释放。

第三步:找到对应的数据库连接

-- 通过 trx_id 关联找到对应的进程 IDSELECTp.idASprocess_id,p.user,p.host,p.db,p.command,p.time,p.state,p.info,t.trx_id,t.trx_duration_secFROMinformation_schema.PROCESSLIST pJOIN(SELECTtrx_id,trx_mysql_thread_id,TIMESTAMPDIFF(SECOND,trx_started,NOW())AStrx_duration_secFROMinformation_schema.INNODB_TRX)tONp.id=t.trx_mysql_thread_idORDERBYt.trx_duration_secDESC;

输出:

process_id: 1234 user: app_user host: 192.168.1.100:54321 command: Sleep ← 连接处于睡眠状态,没有在执行任何操作 time: 7156 trx_id: 88888 trx_duration_sec: 7156

command = Sleep说明这个连接已经"睡着了",但事务还开着,锁还在持有。

第四步:kill 掉僵尸事务

确认这个进程确实是问题所在后,果断 kill:

KILL1234;

执行后,MySQL 会回滚这个事务,释放所有行锁。

几秒钟内,之前等待的几十个事务陆续拿到锁,写操作恢复正常,API 响应时间回落到 50ms。

事后分析:僵尸事务是怎么产生的

查应用代码,发现问题出在一段批量导入逻辑:

// 有问题的代码DB::beginTransaction();foreach($rowsas$row){// 处理每一行数据$result=$this->processRow($row);// processRow 内部调用了外部 HTTP 接口// 接口超时设置是 30 秒,实际等了 2 小时才超时(配置错误)// 在等待期间,事务一直开着,锁一直持有DB::table('import_records')->insert($result);}DB::commit();

processRow内部调用了一个第三方 HTTP 接口,接口超时配置错误,等了将近两个小时。而整个过程事务一直是开着的,持有的行锁一直没释放。

根本原因:在数据库事务内部做了耗时的外部调用。

从根源上避免僵尸事务

原则一:事务内不做外部调用

// 错误示范:事务内调用 HTTP 接口DB::transaction(function()use($data){$result=Http::post('https://api.example.com/process',$data);// 可能超时DB::table('records')->insert($result->json());});// 正确做法:外部调用移到事务外$result=Http::timeout(5)->post('https://api.example.com/process',$data);DB::transaction(function()use($result){DB::table('records')->insert($result->json());});

原则二:设置合理的事务超时时间

-- 单个事务最长执行时间(秒),超时自动回滚SETSESSIONinnodb_lock_wait_timeout=10;-- 全局配置,写入 my.cnf[mysqld]innodb_lock_wait_timeout=10

原则三:建立长事务监控告警

-- 定时检查是否有超过 60 秒的事务SELECTtrx_id,trx_started,TIMESTAMPDIFF(SECOND,trx_started,NOW())ASduration_sec,trx_rows_locked,trx_queryFROMinformation_schema.INNODB_TRXWHERETIMESTAMPDIFF(SECOND,trx_started,NOW())>60;

把这个查询加入监控,超过阈值触发告警,在影响业务之前就能发现处理。

原则四:连接池设置最大空闲时间

# PHP-FPM + PDO 配置 # 连接空闲超过 60 秒自动断开,防止连接假死持锁 [mysqld] wait_timeout = 60 interactive_timeout = 60

完整排查命令速查

-- 1. 查看所有活跃事务,找出运行时间异常长的SELECTtrx_id,trx_state,trx_started,TIMESTAMPDIFF(SECOND,trx_started,NOW())ASduration_sec,trx_rows_locked,trx_queryFROMinformation_schema.INNODB_TRXORDERBYtrx_startedASC;-- 2. 查看锁等待关系SELECT*FROMinformation_schema.INNODB_LOCK_WAITS;-- 3. 找到僵尸事务对应的进程 IDSELECTp.id,p.user,p.host,p.command,p.timeFROMinformation_schema.PROCESSLIST pJOINinformation_schema.INNODB_TRX tONp.id=t.trx_mysql_thread_idWHERETIMESTAMPDIFF(SECOND,t.trx_started,NOW())>60;-- 4. Kill 掉僵尸事务(替换为实际的 process_id)KILL1234;

总结

僵尸事务的处理步骤:

  1. 监控告警发现写操作大量超时
  2. INNODB_TRX找出运行时间异常长的事务
  3. 关联PROCESSLIST找到对应进程 ID
  4. 确认后KILL释放锁
  5. 事后分析事务为什么没有正常提交,修复代码

预防比治疗重要:事务内不做外部调用、设置锁等待超时、建立长事务监控,三条规则写进团队开发规范。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 1:56:06

Visio进阶:绘制可伸缩的深度神经网络卷积块并实现无缝拼接

1. 为什么需要可伸缩的卷积块图表? 在绘制深度神经网络架构图时,卷积块是最基础的组成单元。传统做法是直接复制粘贴相同尺寸的立方体,但当我们需要表示不同宽度的卷积层(比如不同通道数的卷积核)时,简单拉…

作者头像 李华
网站建设 2026/4/15 6:01:11

2026年智能水杯新核心:揭秘原厂二极管的健康饮水科技

你是否想过,你手中那款能精准控温、智能提醒喝水的“黑科技”水杯,其核心秘密可能就藏在一颗比米粒还小的二极管里?从简单的保温杯到如今集控温、杀菌、水质监测于一体的智能水杯,每一次体验的飞跃,背后都是核心电子元…

作者头像 李华
网站建设 2026/4/12 2:37:12

3步攻克Linux打印难题:开源驱动套件全解析

3步攻克Linux打印难题:开源驱动套件全解析 【免费下载链接】foo2zjs A linux printer driver for QPDL protocol - copy of http://foo2zjs.rkkda.com/ 项目地址: https://gitcode.com/gh_mirrors/fo/foo2zjs 在Linux系统中配置打印机往往是用户面临的一大挑…

作者头像 李华
网站建设 2026/4/13 17:11:07

3分钟获取阿里云盘Refresh Token:告别手动认证的自动化解决方案

3分钟获取阿里云盘Refresh Token:告别手动认证的自动化解决方案 【免费下载链接】aliyundriver-refresh-token QR Code扫码获取阿里云盘refresh token For Web 项目地址: https://gitcode.com/gh_mirrors/al/aliyundriver-refresh-token 解决云存储认证难题&…

作者头像 李华
网站建设 2026/4/15 18:10:09

2026 班主任班级成绩问题查摆与改进反思总结

一、考试概况本次期中考试于2026年4月15日至4月17日进行,我班共有学生45人,涉及语文、数学、英语、物理、化学、历史、地理、生物共8门学科。现将班级整体成绩情况汇报如下:总平均分:75.3分 年级排名:第8名&#xff08…

作者头像 李华