高并发下latch竞争需先通过show engine innodb status的semaphores段确认hash_table->latch的spin rounds per wait是否持续>100及os waits是否快速上涨,再结合perf top或performance_schema定位具体线程与争用源。

高并发下 MySQL 的 Latch 竞争不是配置调小就能缓解的问题,而是内存结构争用暴露了底层设计或负载不匹配的信号。直接关掉 innodb_adaptive_hash_index 或调大 innodb_buffer_pool_instances 可能见效,但若没定位到具体 latch 类型和业务模式,大概率白忙。
怎么快速确认是不是 AHI 的 hash_table->latch 在拖慢系统
别猜,先看 SHOW ENGINE INNODB STATUS\G 输出末尾的 SEMAPHORES 段:
- 找含
hash_table->latch的行,如果Spin rounds per wait持续 > 100,说明 CPU 正在空转抢锁 - 同时观察
OS Waits是否在快速上涨——这代表已退化成系统级等待,性能拐点到了 - 配合
perf top -p $(pgrep mysqld),若频繁看到hash_search或ibuf_bitmap_get_map_page,基本坐实 - MySQL 8.0.22+ 可查
performance_schema.events_waits_current,过滤EVENT_NAME LIKE 'wait/synch/%/hash%'定位具体线程
关闭 AHI 后为什么某些查询反而变慢了
这不是 AHI 回归导致的,是它原本掩盖了索引缺陷:
-
Handler_read_key显著下降、Handler_read_next激增 → 说明本该走索引等值查找的语句,现在退化成范围扫描 - 检查所有高频
WHERE id = ?类查询是否真有主键或唯一索引;没有就加,别指望 AHI 补救 - OLAP 类聚合(如带
GROUP BY+ 子查询)变慢,属于正常现象——AHI 本就不该服务这类场景,应优化执行计划或加覆盖索引 - 关闭后务必跑一次
EXPLAIN FORMAT=TREE对比关键语句,确认执行路径未劣化
Buffer Pool 相关 latch(如 buf_pool_mutex)争用怎么压
这类争用通常指向缓冲池访问热点或配置失配:
- 单实例多核机器上,
innodb_buffer_pool_instances建议设为 CPU 核心数(上限 64),避免所有线程挤同一把 mutex - 若
SHOW ENGINE INNODB STATUS中buf_block->lock等待突出,且业务存在大量随机二级索引更新,优先关 AHI(innodb_adaptive_hash_index = OFF) - 全表扫描多?控制
innodb_old_blocks_pct防止热数据被刷出,或加大innodb_buffer_pool_size减少物理读 - 注意:调整
innodb_buffer_pool_instances必须重启生效;运行时改无效
为什么 perf 或 SHOW ENGINE 看到的 latch 等待信息容易误判
因为它们全是快照,不是实时流:
-
SHOW ENGINE INNODB STATUS的SEMAPHORES段只保留最近 15 秒统计,单次执行可能错过尖峰 -
OS WAIT ARRAY INFO里 “reserving” 和 “waiting” 混在一起,看不出是哪个 latch 类型在卡住 -
INFORMATION_SCHEMA.INNODB_METRICS中的累加计数(如innodb_buffer_pool_mutex_spin_waits)无时间粒度,无法定位瞬时问题 - 真正要定位页级争用源,得开
performance_schema的对应 instruments,并结合OBJECT_INSTANCE_BEGIN地址反推 buffer header,再关联到表空间与页号——这步跳过,就只能靠猜
Latch 竞争从来不是孤立现象。它要么是 SQL 逻辑读太高打穿缓存链表,要么是事务持有锁太久让 buffer page 反复被重入,要么是索引缺失迫使引擎反复扫描同一组页。盯住 hash_table->latch 或 buf_pool_mutex 本身没意义,得回溯到哪条 SQL、哪个事务、哪张表在高频触碰这些内存结构。











