Double Write Buffer:防止页损坏的保障机制
部分写问题(Partial Page Write) 问题 页大小16KB > 磁盘块大小4KB,写入过程中系统崩溃,导致页损坏。 写入16KB页(4个磁盘块): ┌──────┬──────┬──────┬──────┐ │ 4KB │ 4KB │ 4KB │ 4KB │ └──────┴──────┴──────┴──────┘ ✅ ✅ ❌ ❌ 已写入 已写入 未写入 未写入 ↑ 系统崩溃 结果:页损坏(部分写) redo log无法恢复: redo log记录的是页的逻辑修改(如"将id=1的name改为Alice") 如果页本身损坏,无法应用redo log Double Write Buffer解决方案 原理 先写双写缓冲区(连续空间),再写数据文件(离散空间)。 写入流程: 1. 脏页 → Double Write Buffer(共享表空间,连续2MB) 2. Double Write Buffer → 磁盘(刷盘,原子操作) 3. 脏页 → 数据文件(离散写入) 崩溃恢复: IF 数据文件页损坏 THEN 从Double Write Buffer恢复页 ELSE 使用redo log恢复 END IF Double Write Buffer结构 1. 内存结构 Buffer Pool ├─ 脏页1(16KB) ├─ 脏页2(16KB) └─ ... Double Write Buffer(内存,2MB) ├─ 页1(16KB) ├─ 页2(16KB) ├─ ... └─ 页128(16KB) 2. 磁盘结构 共享表空间(ibdata1) ┌─────────────────────────────────┐ │ 数据字典 │ ├─────────────────────────────────┤ │ Double Write Buffer(2MB,连续) │ ← 双写缓冲区 │ ├─ 区1(1MB = 64页) │ │ └─ 区2(1MB = 64页) │ ├─────────────────────────────────┤ │ Undo Log │ └─────────────────────────────────┘ 写入流程 1. 正常写入 1. 脏页刷新触发 ├─ Buffer Pool中的脏页批量刷新(如128个页) 2. 写入Double Write Buffer(内存) ├─ 128个页复制到Double Write Buffer 3. 写入共享表空间(磁盘,顺序写) ├─ fsync刷盘(原子操作) ├─ 2MB连续空间,1次IO 4. 写入数据文件(磁盘,随机写) ├─ 128个页分别写入各自的表空间文件 ├─ 随机IO,多次寻址 5. 清空Double Write Buffer(内存) 关键: ...