
MySQL内部Latch是什么,和锁(Lock)有什么区别
Latch是InnoDB内部的轻量级同步机制,用于保护内存数据结构(比如buffer pool的page、LRU链表、索引btree节点),不是SQL层的事务锁。它不持久、不记录在INFORMATION_SCHEMA.INNODB_TRX里,也不参与死锁检测——出问题时你看到的是“卡住”或“慢查询突增”,而不是Deadlock found when trying to get lock。
常见误判:把show engine innodb status里反复出现的os_waits高、spin_waits飙升,当成是事务锁争用,其实大概率是latch竞争。
怎么定位Latch热点:从INNODB_METRICS和PERFORMANCE_SCHEMA查
MySQL 5.6+ 开始暴露部分latch统计,关键入口是INNODB_METRICS表,重点关注带latch前缀的指标:
-
innodb_buffer_pool_pages_latched:当前被latch保护的page数,持续高于buffer pool总页数10%就值得警惕 -
innodb_buffer_pool_wait_free:线程等待空闲page的次数,高说明buf_pool->mutex或buf_pool->flush_list_mutex争用严重 -
innodb_log_write_requests与innodb_log_waits比值骤降,可能反映log_sys->mutex瓶颈
更细粒度要用PERFORMANCE_SCHEMA(需提前开启):
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'wait/synch/%/mutex/innodb/%';
之后查performance_schema.events_waits_summary_global_by_event_name,过滤EVENT_NAME含mutex/innodb/buf_pool或log_sys的行,看SUM_TIMER_WAIT和COUNT_STAR。
常见Latch瓶颈场景和对应调优动作
不是所有latch高都该调参,得先确认是不是真实瓶颈:
- 单实例高并发小事务写入(如IoT打点),
buf_pool->mutex常成瓶颈 → 增大innodb_buffer_pool_instances(建议=CPU核心数,但不超过64) - 大量随机二级索引更新导致
btr_search_latch争用 → 关闭自适应哈希索引:innodb_adaptive_hash_index = OFF(MySQL 8.0默认已关) - 日志刷盘慢引发
log_sys->mutex排队 → 检查磁盘IOPS、调大innodb_log_file_size(但别超4GB)、避免sync_binlog=1+innodb_flush_log_at_trx_commit=1双严模式共存 - Buffer Pool频繁扫描LRU链表(如全表扫描多)→ 控制
innodb_old_blocks_pct防污染,或加大innodb_buffer_pool_size减少物理读
为什么SHOW ENGINE INNODB STATUS里的latch信息容易误读
它的SEMAPHORES段只显示最近15秒的等待摘要,且OS WAIT ARRAY INFO中“reserving”和“waiting”混在一起,看不出是哪个latch类型。更麻烦的是,它不区分spin wait和OS wait:spin是CPU空转,OS wait才是真阻塞。如果spin_waits远高于os_waits,说明CPU够但临界区代码太长(比如大page压缩、复杂purge逻辑),这时加核反而恶化;反之os_waits高,才是I/O或配置问题。
真正要盯的,是PERFORMANCE_SCHEMA里按事件名聚合的等待时间分布,以及INNODB_METRICS的趋势变化——静态快照没意义,必须看连续采样。










