Page锁争用实为刷页链路瓶颈,源于page cleaner线程竞争IO或双写缓冲区,非真正页级锁;应优先检查脏页比例、刷页速率、双写文件配置及buffer pool实例与chunk分配。

Page锁争用不是“锁粒度”问题,而是刷页链路瓶颈
MySQL 8.0 的 Page 锁争用(常被误称为“页级锁”)实际并不存在独立的 Page 级锁机制。InnoDB 对数据页的并发控制仍基于行锁 + 间隙锁,所谓“Page 锁争用”现象,99% 是 page cleaner 线程在刷脏页时,多个线程竞争同一磁盘 IO 资源或双写缓冲区写入点导致的间接阻塞,表现为 innodb_row_lock_waits 升高、log_write_wait 延迟增加、Pages flushed 速率下降。
典型错误归因是看到 SHOW ENGINE INNODB STATUS 中大量 log wait 或 flush wait,就去调 innodb_page_size 或改隔离级别——这完全跑偏。Page 相关争用不来自 SQL 执行层,而来自底层物理页落盘路径。
优先检查 page cleaner 是否被拖慢
Page cleaner 负责把 buffer pool 里的脏页异步刷到磁盘。如果它跟不上脏页生成速度,就会堆积,后续 DML 必须等空闲页或触发同步刷页(sync flush),造成明显卡顿。
- 查当前脏页比例:
SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';,再除以Innodb_buffer_pool_pages_total;超过 15% 就有风险 - 看刷页速率:
SHOW STATUS LIKE 'Innodb_pages_written';每秒写入页数是否持续低于 100(SSD 场景下应 ≥300) - 确认
innodb_adaptive_flushing是否开启(默认 ON),关闭它会导致刷页节奏僵化,加剧突发写入下的抖动 - 避免手动调
innodb_max_dirty_pages_pct到 90 —— 这等于放任脏页堆积,不是“提升吞吐”,是埋雷
双写缓冲区(Doublewrite Buffer)争用才是真因
MySQL 8.0.30+ 引入的 innodb_doublewrite_files 就是为解决这个:当多线程并发刷页时,所有双写页都挤向 ibdata1 的固定区域,形成单点 IO 锁竞争。这不是 bug,是旧架构的物理限制。
启用多文件双写需同时满足:
-
innodb_doublewrite = ON(必须,关了会丢数据) - MySQL ≥ 8.0.30
-
innodb_doublewrite_files设为 2–64 之间整数,**建议 ≤ 后端 NVMe 设备数量**(如挂 2 块 SSD,设 2;1 块就别设,设 4 反而降低吞吐) - 配置写入 my.cnf 的
[mysqld]段,重启生效(SET GLOBAL不支持动态修改)
验证是否生效:SHOW VARIABLES LIKE 'innodb_doublewrite%'; 应显示 innodb_doublewrite_files 值,且 error log 出现 Doublewrite files created
buffer pool 实例与 chunk 分配不当会放大争用
大 buffer pool(>1GB)下,若 innodb_buffer_pool_instances 过小(如仍为默认 1),所有线程都抢同一个 LRU list 和 flush list,page cleaner 线程无法并行处理不同实例的脏页,导致刷页串行化。
正确做法:
- buffer pool 总大小 ÷ 实例数 = 每个实例大小,**必须是
innodb_buffer_pool_chunk_size(默认 128MB)的整数倍** - 例如 12GB buffer pool,设
innodb_buffer_pool_instances = 12,则每实例 1GB,刚好 8 × 128MB - 同时确保
innodb_buffer_pool_chunk_size未被意外调小(如设成 1MB),否则 chunk 数暴增,管理开销反升 - 监控
Innodb_buffer_pool_wait_free:该值升高说明实例间内存分配不均或 chunk 不对齐,导致等待空闲页
Page 层争用没有银弹。它不像行锁能靠 SQL 改写绕开,而是直击硬件与内核协同的边界——IO 调度器、NVMe 队列深度、甚至 ext4 的 journal 模式都会参与进来。调参只是表象,真正要盯住的是 Pages flushed/sec 和 log write time 这两个硬指标,它们不会说谎。


















