MySQL 8.4中监控长事务和锁等待的核心是:先用INNODB_TRX筛选运行超30秒且TRX_QUERY为空或状态为LOCK WAIT的事务,再通过开启performance_schema.data_lock_waits采集并关联查询精准定位阻塞关系;初筛用SHOW STATUS LIKE 'innodb_row_lock_current_waits'快速判断是否存在锁等待。

MySQL 8.4 中监控长事务和锁等待,核心就两件事:先快速筛出“还在跑、没提交”的事务,再精准定位“谁卡着谁”。INNODB_LOCK_WAITS 已彻底消失,performance_schema.data_lock_waits 是唯一可靠入口,但默认不采集——不手动开开关,查出来永远是空。
查长事务:只看 INFORMATION_SCHEMA.INNODB_TRX 就够了
这是最准、权限最低、响应最快的入口。它反映真实持有锁的事务,比 SHOW PROCESSLIST 可靠得多(后者常只显示等待者,不显示阻塞源)。
- 关键字段必须关注:
TRX_STARTED(启动时间)、TRX_STATE(状态,LOCK WAIT表示正在等锁)、TRX_QUERY(当前 SQL),TRX_ISOLATION_LEVEL(RR 级别下范围查询更容易持锁) - 线上阈值建议设为 10–30 秒,不是等它“明显长”才干预:
SELECT TRX_ID, TRX_MYSQL_THREAD_ID, TRX_QUERY, TIMESTAMPDIFF(SECOND, TRX_STARTED, NOW()) AS duration, TRX_STATE FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TIMESTAMPDIFF(SECOND, TRX_STARTED, NOW()) > 30;
-
TRX_QUERY为空 ≠ 没事——可能是只执行了BEGIN,后续没 SQL,但之前操作已持锁;ORM 框架(如 Django)默认开启事务,HTTP 请求未结束 = 事务未提交
查锁等待:必须开 performance_schema 开关,否则查不到
MySQL 8.4 彻底移除 INNODB_LOCK_WAITS 和 INNODB_LOCKS,直接查它们永远返回空。真正可用的是 performance_schema.data_lock_waits,但它默认关闭采集。
- 先确认开关是否打开:
SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/lock/innoDB/%';
确保wait/lock/innoDB/lock行的ENABLED为YES - 再启用消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('global_instrumentation', 'thread_instrumentation'); - 关联查询时注意字段类型:
BLOCKING_ENGINE_TRANSACTION_ID必须连INNODB_TRX.trx_id,不能误连trx_mysql_thread_id(那是线程 ID,类型不匹配,结果为空):SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_pid, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_pid, b.trx_query blocking_query FROM performance_schema.data_lock_waits w JOIN INFORMATION_SCHEMA.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID JOIN INFORMATION_SCHEMA.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID;
初筛有没有锁等待:用 SHOW STATUS LIKE 'innodb_row_lock_current_waits'
这个命令权限低、响应快,适合线上秒级拍快照。返回值 > 0 就说明此刻有事务在等行锁。
- 它不是累计值,归零不代表问题消失——可能只是锁刚释放,或等待刚好超时(默认
innodb_lock_wait_timeout=50) - 搭配看
innodb_row_lock_time_avg:如果平均等待时间突然从 0.2ms 跳到 40ms+,基本可断定有慢事务或未提交事务拖累 - 别依赖它做根因分析,只用作“有没有问题”的第一反应信号
防长事务:配置 + 应用层双控,不能只靠监控
监控是事后手段,真正要命的是事务生命周期失控。锁本身不是问题,不及时释放才是。
- 配置层必须调:
SET GLOBAL innodb_lock_wait_timeout = 10;(默认 50),让等待者早点失败报错Lock wait timeout exceeded,而不是无限等 - 应用层禁止跨 HTTP 请求延续事务上下文,所有数据库操作必须明确包裹在
BEGIN/COMMIT或等价事务管理块中 -
AUTOCOMMIT=0的连接一旦忘了COMMIT,后续所有语句都在同一个未提交事务里累积锁——这种连接应被严格限制或自动回收
最易被忽略的点:即使你把所有开关都开了、SQL 都写对了,如果 performance_schema 内存不足(performance_schema_max_table_instances 或 table_size 过小),data_lock_waits 仍可能丢数据。查不到不一定是没锁,得顺手检查 performance_schema 相关内存参数是否撑得住当前负载。


















