Doublewrite不阻塞读操作,因其仅在脏页刷盘时介入,而读请求直接从Buffer Pool返回数据,完全绕过Doublewrite区域;它仅作为刷盘前的安全备份,与SELECT等读操作无任何路径交集。

Doublewrite 本身不阻塞读,因为它根本不在读路径上——它只在脏页刷盘(flush)时介入,而读操作绝大多数时候直接从 Buffer Pool 返回数据。
Doublewrite 只在刷脏页时触发,和 SELECT 无关
读请求(SELECT)走的是 Buffer Pool 查找路径:命中就返回,未命中才去磁盘加载页。整个过程完全绕过 Doublewrite 区域。Doublewrite 的唯一作用是“为即将写入磁盘的脏页做个安全备份”,它发生在后台线程(如 Page Cleaner)或 checkpoint 触发刷盘时,不是每个 UPDATE 都立刻触发刷盘。
-
UPDATE语句执行后,只修改 Buffer Pool 中的页、写 redo log、加锁、记录 undo,不碰 Doublewrite - 真正写 Doublewrite buffer 是后续异步刷脏页阶段的事,和当前事务是否提交、是否被读取毫无关系
- 即使大量
UPDATE导致 Buffer Pool 脏页激增,只要没到刷盘阈值(如innodb_max_dirty_pages_pct),Doublewrite 就完全沉默
刷盘阶段的 Doublewrite 写入是顺序 I/O,不锁行也不锁表
当 Page Cleaner 线程开始刷脏页时,它把一批页先 memcpy 到内存中的 Doublewrite buffer(128 页 / 2MB),再顺序写入磁盘上的 Doublewrite 区域(ibdata1 或独立 dblwrlog 文件)。这个过程:
- 不持有任何用户行锁、表锁或意向锁
- 不阻塞正在执行的
SELECT,因为读操作只依赖 Buffer Pool 和 page latch(轻量级内存锁),与刷盘线程无竞争 - 顺序写比随机写快得多,即使磁盘慢,也只是拖慢刷盘速度,不会让读请求排队等待
容易误判“Doublewrite 导致读变慢”的真实原因
如果你观察到大量 UPDATE 后 SELECT 延迟升高,问题几乎肯定不在 Doublewrite 本身,而是下面这些更常见的干扰项:
- Buffer Pool 压力大:脏页太多 → Free List 不足 → 新读请求要等 LRU 淘汰或刷脏页腾空间 → 表现为
innodb_buffer_pool_wait_free上升 - Redo log 刷盘争抢:
innodb_flush_log_at_trx_commit = 1+ 大事务 → 每次COMMIT都 fsync redo → I/O 队列积压,间接拖慢所有磁盘操作(包括刷脏页,进而延长 Doublewrite 等待) - Checkpoint 频繁:
innodb_log_file_size过小 → redo 循环快 → 被迫高频 checkpoint → 触发密集刷脏页 → Doublewrite 写入量陡增,但瓶颈其实是磁盘响应能力,不是 Doublewrite 逻辑 - 锁竞争:高并发
UPDATE锁住热点行 → 后续SELECT ... FOR UPDATE或带锁读被阻塞 → 看似“读慢”,实为锁等待
真正要盯的,不是 Doublewrite 开关,而是它背后暴露的硬件水位:如果 Innodb_dblwr_pages_written 持续远高于 Innodb_dblwr_writes(比如前者是后者的 100 倍),说明 Doublewrite buffer 频繁溢出、刷盘跟不上,这时候该换低延迟 SSD,而不是怀疑 Doublewrite 阻塞了谁。它从来就没打算参与读写并发调度。











