MySQL 8.0+ 中 wait_events 可定位内核级互斥锁竞争,但仅限其自实现的 mutex/rwlock(如 wait/synch/mutex/innodb/buf_pool_mutex),不直接暴露操作系统 futex 等原生锁;需启用 performance_schema、开启对应 instruments 并关联 threads 和 statements 表追溯 SQL 根因。

MySQL 8.0+ 中的 wait_events(实际指性能模式中的 events_waits_* 表,尤其是 events_waits_current 和 events_waits_history_long)可用于定位内核级互斥锁(如 mutex、rwlock)引发的并发竞争问题,但需注意:MySQL 本身不直接暴露操作系统内核锁(如 futex、pthread_mutex_t),而是监控其存储引擎和服务器层自实现的同步对象——这些对象在性能模式中统一归类为 wait/synch/mutex/* 或 wait/synch/rwlock/* 等事件。
确认性能模式已启用并配置合理
Wait events 数据来源于 performance_schema,必须提前开启且保留足够采样深度:
- 启动时确保
performance_schema=ON(默认开启,但生产环境可能被禁用) - 调整关键参数以捕获长时等待:
SET GLOBAL performance_schema_events_waits_history_long_size = 1000000;SET GLOBAL performance_schema_max_thread_instances = 1000; - 启用 mutex/rwlock 等同步事件采集:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'wait/synch/mutex/%' OR NAME LIKE 'wait/synch/rwlock/%';
识别高延迟或高频次的互斥锁事件
从 events_waits_history_long 中筛选出等待时间长、次数多的对象,重点关注 SOURCE 和 OBJECT_NAME 字段:
- 查最耗时的 10 个 mutex 等待:
SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT, AVG_TIMER_WAIT, SOURCE FROM performance_schema.events_waits_history_long WHERE EVENT_NAME LIKE 'wait/synch/mutex/%' GROUP BY EVENT_NAME ORDER BY SUM_TIMER_WAIT DESC LIMIT 10; - 查正在发生中的阻塞链(需结合
events_waits_current和线程状态):SELECT THREAD_ID, EVENT_NAME, TIMER_WAIT, SOURCE, OBJECT_NAME FROM performance_schema.events_waits_current WHERE EVENT_NAME LIKE 'wait/synch/mutex/%' AND TIMER_WAIT > 1000000000; -- 超过 1 秒
典型高竞争锁示例:wait/synch/mutex/innodb/buf_pool_mutex → 缓冲池全局锁争用,常见于大量随机写入或小 buffer pool 配置;wait/synch/mutex/innodb/log_sys_mutex → redo 日志系统锁,多线程高频率 commit 易触发;wait/synch/rwlock/innodb/hash_table_locks → 自适应哈希索引锁,复杂查询或非选择性索引扫描可能加剧竞争。
关联线程与 SQL 上下文定位根因
单看锁名不够,需将等待事件映射到具体会话和 SQL:
- 通过
THREAD_ID关联performance_schema.threads获取PROCESSLIST_ID:SELECT t.PROCESSLIST_ID, t.PROCESSLIST_INFO, w.EVENT_NAME, w.TIMER_WAIT FROM performance_schema.events_waits_current w JOIN performance_schema.threads t ON w.THREAD_ID = t.THREAD_ID WHERE w.EVENT_NAME LIKE 'wait/synch/mutex/innodb/log_sys_mutex' AND w.TIMER_WAIT > 500000000; - 若启用了
events_statements_*,还可追溯该线程最近执行的语句:SELECT DIGEST_TEXT FROM performance_schema.events_statements_history WHERE THREAD_ID = ? ORDER BY EVENT_ID DESC LIMIT 1;
例如发现多个线程长时间等待 log_sys_mutex,同时对应线程都在执行 INSERT ... SELECT 或大批量 INSERT,说明日志刷盘成为瓶颈,可考虑调大 innodb_log_buffer_size、启用 innodb_flush_log_at_trx_commit=2(权衡持久性),或拆分批量事务。
区分 MySQL 层锁与真正 OS 内核锁
需要明确:MySQL 的 wait/synch/mutex/* 是其内部模拟的同步原语(如 os_event 封装的 pthread_mutex 或 spinlock),并非直接采集 Linux futex 或 pthread_mutex_lock 系统调用。若需分析真正的内核级锁竞争(如 mysqld 进程被调度器阻塞、CPU 抢占、页缺失等),应使用外部工具:
-
perf record -e sched:sched_switch,sched:sched_stat_sleep -p $(pidof mysqld)分析调度延迟 -
pstack $(pidof mysqld)查看线程栈中是否卡在pthread_mutex_lock等系统调用 -
cat /proc/$(pidof mysqld)/stack快速抓当前所有线程内核态栈
这类分析通常用于排查 MySQL 无明显慢查询但整体响应迟钝的场景,属于更底层的系统诊断范畴。


















