MySQL performance_schema events_transactions_current 怎样抓住长事务
来源:17golang原创
时间:2026-11-14 03:25:12 186浏览 收藏
线上出现锁等待时,先不要把所有慢 SQL 都当成根因。对“事务还没结束、已经持续很久”的判断,MySQL Performance Schema 已经给了一个直接入口:performance_schema.events_transactions_current。筛选 STATE = 'ACTIVE'、END_EVENT_ID IS NULL,再把 TIMER_WAIT 从皮秒换算成秒,就能先抓住当前仍在运行的长事务。
本文只讨论当前事务、长事务和锁诊断,不把历史事务表当成实时列表,也不把事务持续时间直接等同于锁等待时间。
先确认当前事务事件确实在采集
events_transactions_current 按线程保存最近一个被监控的当前事务事件,每个线程最多对应一行。若事务 instrument 没开,或者 consumer 没开,查询为空并不代表系统没有事务。
-- 先查看事务采集开关,避免把“未采集”误判成“没有长事务” SELECT NAME, ENABLED, TIMED FROM performance_schema.setup_instruments WHERE NAME = 'transaction'; -- current consumer 决定是否维护当前事务表 SELECT NAME, ENABLED FROM performance_schema.setup_consumers WHERE NAME = 'events_transactions_current'; -- 仅在确认允许动态调整采集时执行;TIMED=YES 才能获得耗时字段 UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME = 'transaction'; UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_transactions_current';

生产环境调整前要评估采集开关的影响,并确认账号有访问 Performance Schema 设置表的权限。文章中的 UPDATE 是配置示例,不代表已经在你的实例执行。
用 TIMER_WAIT 抓仍然活跃的长事务
MySQL 8.4 文档说明,当前事件尚未结束时,END_EVENT_ID 为 NULL,TIMER_WAIT 表示从开始到当前时刻经过的时间,单位是皮秒。下面用 300 秒作为排查阈值,你可以按业务事务的正常时长调整。
-- 300 秒 = 300 × 10^12 皮秒;只看仍处于 ACTIVE 的当前事务
SELECT
THREAD_ID,
EVENT_ID,
STATE,
ROUND(TIMER_WAIT / 1000000000000, 1) AS elapsed_seconds,
ACCESS_MODE,
ISOLATION_LEVEL,
AUTOCOMMIT,
NESTING_EVENT_ID,
NESTING_EVENT_TYPE
FROM performance_schema.events_transactions_current
WHERE END_EVENT_ID IS NULL
AND STATE = 'ACTIVE'
AND TIMER_WAIT IS NOT NULL
AND TIMER_WAIT >= 300 * 1000000000000
ORDER BY TIMER_WAIT DESC;
这里的三个条件各有作用:END_EVENT_ID IS NULL 排除已经结束但仍留在当前表的事件;STATE = 'ACTIVE' 把关注点放在尚未提交或回滚的事务;TIMER_WAIT IS NOT NULL 避免未计时的事件进入比较。若结果为空,先回到上一节检查采集开关和查询权限。
别把事务时间和锁等待时间混为一谈
长事务只是“事务保持活动的时间很长”,它可能在等待业务输入、持有锁、执行慢查询,或者只是应用忘记提交。要判断它是否正在阻塞别人,需要把事务线程与 performance_schema.data_lock_waits 关联。
-- requesting 是等待锁的一方,blocking 是持有阻塞锁的一方
SELECT
w.REQUESTING_THREAD_ID,
w.BLOCKING_THREAD_ID,
ROUND(r.TIMER_WAIT / 1000000000000, 1) AS requesting_seconds,
ROUND(b.TIMER_WAIT / 1000000000000, 1) AS blocking_seconds,
r.STATE AS requesting_state,
b.STATE AS blocking_state,
r.ACCESS_MODE AS requesting_mode,
b.ACCESS_MODE AS blocking_mode
FROM performance_schema.data_lock_waits AS w
LEFT JOIN performance_schema.events_transactions_current AS r
ON r.THREAD_ID = w.REQUESTING_THREAD_ID
LEFT JOIN performance_schema.events_transactions_current AS b
ON b.THREAD_ID = w.BLOCKING_THREAD_ID
WHERE r.END_EVENT_ID IS NULL
OR b.END_EVENT_ID IS NULL;

如果 BLOCKING_THREAD_ID 对应的事务持续时间很长,同时又出现在多个等待关系中,它更值得优先处理。但不要仅凭这张表直接终止会话:先结合业务确认是否处在必须原子完成的流程,再决定提交、回滚或让应用修复事务边界。
需要更具体的引擎信息时再看 InnoDB 状态
events_transactions_current 适合回答“哪个线程有一笔仍活跃的事务、已经持续多久、事务属性是什么”。当问题进一步变成“具体锁住了哪个索引记录、出现了什么 InnoDB 锁描述”,可以补充:
-- 该命令需要 PROCESS 权限;它提供 InnoDB Monitor 的引擎侧状态 SHOW ENGINE INNODB STATUS;
它们的分工可以这样记:当前事务表负责按线程和耗时排序,data_lock_waits 负责看等待与阻塞关系,InnoDB 状态负责补充引擎侧细节。三者不是同一份数据,也不能互相替代。
常见误区与速查结论
- 查询
events_transactions_history只能看到已经结束的近期事务,不能代替 current 表抓实时长事务。 TIMER_WAIT是皮秒,不是秒;换算时使用1000000000000,不要直接和 300 比较。- 事务很长不必然代表它正在阻塞别人;是否阻塞要看
data_lock_waits的 blocking 关系。 - 事务事件边界和服务器事务状态基本一致,但只访问非事务表的语句不会让 Performance Schema 事务事件进入同一事务边界。
排查顺序可以压缩成一句话:先确认采集,再用 END_EVENT_ID、STATE 和 TIMER_WAIT 找出活动长事务,随后用线程 ID 关联锁等待,最后用 InnoDB 状态补足记录级信息。
相关问题
为什么 TIMER_WAIT 是 NULL?
通常是对应 instrument 没有开启计时,即 TIMED 不是 YES。先查看 setup_instruments,不要把 NULL 当成零秒。
events_transactions_current 为什么看不到我刚执行的事务?
检查 Performance Schema 是否启用、transaction instrument 和 current consumer 是否开启,并确认事务确实访问了事务性存储引擎。自动提交模式下,每条使用事务性引擎的语句也可能形成很短的隐式事务。
长事务应该立刻 KILL 吗?
不建议只按时长自动处理。先确认它是否是阻塞链中的 blocking 方、是否处在可安全回滚的业务阶段,再由业务负责人决定提交、回滚、终止会话或修复连接池的事务边界。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习