MySQL change buffer

當需要更新一個數據頁時,如果數據頁在內存中就直接更新,而如果這個數據頁還沒有在內存中的話,在不影響數據一致性的前提下,InooDB 會將這些更新操作緩存在 change buffer 中,這樣就不需要從磁盤中讀入這個數據頁了。在下次查詢需要訪問這個數據頁的時候,將數據頁讀入內存,然後執行 change buffer 中與這個頁有關的操作。通過這種方式就能保證這個數據邏輯的正確性。

需要說明的是,雖然名字叫作 change buffer,實際上它是可以持久化的數據。也就是說,change buffer 在內存中有拷貝,也會被寫入到磁盤上。

將 change buffer 中的操作應用到原數據頁,得到最新結果的過程稱爲 merge。除了訪問這個數據頁會觸發 merge 外,系統有後臺線程會定期 merge。在數據庫正常關閉(shutdown)的過程中,也會執行 merge 操作。

顯然,如果能夠將更新操作先記錄在 change buffer,減少讀磁盤,語句的執行速度會得到明顯的提升。而且,數據讀入內存是需要佔用 buffer pool 的,所以這種方式還能夠避免佔用內存,提高內存利用率。

使用場景

change buffer 只限於用在普通索引的場景下,而不適用於唯一索引。那麼,現在有一個問題就是:普通索引的所有場景,使用 change buffer 都可以起到加速作用嗎?

因爲 merge 的時候是真正進行數據更新的時刻,而 change buffer 的主要目的就是將記錄的變更動作緩存下來,所以在一個數據頁做 merge 之前,change buffer 記錄的變更越多(也就是這個頁面上要更新的次數越多),收益就越大。

因此,對於寫多讀少的業務來說,頁面在寫完以後馬上被訪問到的概率比較小,此時 change buffer 的使用效果最好。這種業務模型常見的就是賬單類、日誌類的系統。

反過來,假設一個業務的更新模式是寫入之後馬上會做查詢,那麼即使滿足了條件,將更新先記錄在 change buffer,但之後由於馬上要訪問這個數據頁,會立即觸發 merge 過程。這樣隨機訪問 IO 的次數不會減少,反而增加了 change buffer 的維護代價。所以,對於這種業務模式來說,change buffer 反而起到了副作用。

change buffer 與 redo log

redo log 主要節省的是隨機寫磁盤的 IO 消耗(轉成順序寫),而 change buffer 主要節省的則是隨機讀磁盤的 IO 消耗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章