Change Buffer(舊稱 Insert Buffer)是 InnoDB 針對非唯一輔助索引的寫入優化子系統。本文從定義、原理、內部結構、合併調度、缺點、監控六個維度進行系統性剖析。
ibdata1當目標索引頁不在 Buffer Pool:
search_key = space_id(4B) + marker(1B) + page_offset(4B)space | marker | offset | metadata | secondary_index_recordInsert Buffer Bitmap 頁記錄各索引頁剩餘空間,保證合併可行| 模式 | 觸發條件 | 執行者 | 用戶感知 |
|---|---|---|---|
| 主動合併 | 過去 1s I/O < 5% 系統能力 或 每 10s 必執行 | 主線程發 Async I/O 讀頁 → I/O Handler 線程合併 | 無感知 |
| 被動合併 | 頁分裂/合併、IB 過大壓縮、優化失敗需讀頁 | 用戶線程同步執行 | 可感知延遲 |
search_key.ibd 单獨複製恢復會導致輔助索引不全,需 REPAIR TABLE 重建innodb_change_buffer_max_size),寫密集場景擠佔熱數據緩存SHOW ENGINE INNODB STATUS \G
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2,
41 inserts, 41 merged recs, 499 merges
Hash table size 3984403, node heap has 967 buffer(s)
14.66 hash searches/s, 64.65 non-hash searches/s
size = seg size - (1 + free list len)(含頭頁)seg size:Change Buffer 總頁數(預設 2 頁 = 32KB)merges:總合併次數merged recs:合併記錄數discarded:被丟棄的合併(頁已在內存直接修改)innodb_change_buffering = inserts|none|all|changes|purges -- 預設 all innodb_change_buffer_max_size = 50 -- 佔 Buffer Pool 最大百分比
Change Buffer 是機械硬碟時代為緩解隨機 I/O 而生的經典設計。SSD 普及後,其邊際收益下降,但對寫入密集、非唯一索引多的 OLTP 仍有價值。建議:保持開啟,監控 Ibuf 指標,若合併頻繁導致被動合併延遲明顯,考慮調低 max_size 或針對性關閉特定表索引的 change buffering(MySQL 8.0+ 支援表級控制)。