寫緩存(Change Buffer) 是一種特殊的數據結構,用於在對數據變更時,如果數據所在的數據頁沒有在 buffer pool 中的話,在不影響數據一致性的前提下,InnoDB 引擎會將對數據的操作緩存在 Change Buffer 中,這樣就省去了從磁盤中讀入這個數據頁。
將數據頁從磁盤讀入內存中涉及隨機 IO 訪問,這也是數據庫里面成本最高的操作之一,而利用寫緩存(Change Buffer)可以減少 IO 操作,從而提升數據庫性能。
關於 MySQL 寫緩存(Change Buffer),我們先來看看 InnoDB 的技術架構圖:
Change Buffer 是 Buffer Pool 中的一部分,雖然 Change Buffer 名字叫 Buffer ,但是它也是可以持久化的,在右邊的 System Tablespace 中可以看到持久化 Change Buffer 的空間。觸發寫緩存(Change Buffer)持久化操作有以下幾種情況:
- 1、數據庫空閑時,后台有線程定時持久化
- 2、數據庫緩沖池不夠用時
- 3、數據庫正常關閉時
- 4、redo log 寫滿時
再單獨看看 Change Buffer 的架構圖,如下所示:
圖中詳細的描述了 Change Buffer 的功能,Change Buffer 中的數據最終還是會刷回到數據所在的原始數據頁中,Change Buffer 數據應用到原始數據頁,得到新的數據頁的過程稱之為 merge。merge 過程中只會將 Change Buffer 中與原始數據頁有關的數據應用到原始數據頁,以下三種情況會發生 merge 操作:
- 1、原始數據頁加載到 Buffer Pool 時。
- 2、系統后台定時觸發 merge 操作。
- 3、MySQL 數據庫正常關閉時。
Change Buffer 的相關設置
上面就是寫緩存(Change Buffer)的相關知識,寫緩存(Change Buffer)我們也是可以使用命令參數來控制,MySQL 數據庫提供了兩個對寫緩存(Change Buffer)的參數。
1、innodb_change_buffer_max_size
innodb_change_buffer_max_size 表示 Change Buffer 最大大小占 Buffer Pool 的百分比,默認為 25%。最大可以設置為 50%。
2、innodb_change_buffering
innodb_change_buffering 參數用來控制對哪些操作啟用 Change Buffer 功能,默認是:all。innodb_change_buffering 參數有以下幾種選擇:
--all: 默認值。開啟buffer inserts、delete-marking operations、purges
--none: 不開啟change buffer
--inserts: 只是開啟buffer insert操作
--deletes: 只是開delete-marking操作
--changes: 開啟buffer insert操作和delete-marking操作
--purges: 對只是在后台執行的物理刪除操作開啟buffer功能
對上面寫緩存(Change Buffer)如果你還是雲里霧里的話,那么我們就用一個案例來說明一下 Change Buffer ,首先我們向數據庫中插入兩條數據:
mysql> insert into t(id,k) values(id1,k1),(id2,k2);
結合下面這張圖來分析這兩條插入語句。
假設當前是 K索引樹的狀態,K1 所在的數據頁 page1 在 Buffer Pool 中,k2 所在的數據頁不在 Buffer Pool 中,來看看這兩條語句的執行流程:
1、對於 k1 這條數據,Page 1 在內存中,所以直接更新內存,不會使用到 Change Buffer;
2、k2 對應的數據頁 Page 2 沒有在內存中,就在內存的 change buffer 區域,記錄下“我要往 Page 2 插入一行”這個信息,這個地方及其關鍵,並沒有從磁盤中將 page2 加載到內存。
3、將上述兩個動作記入 redo log 中(圖中 3 和 4)。
4、后台線程會定時將 page1 和 Change Buffer 中的數據持久化
主要地方在於步驟二,這就是寫緩存(Change Buffer)提高性能的地方,雖然 page2 並沒有在內存中,但是並沒有妨礙我們往數據庫 page2 中插入數據,這就是寫緩存(Change Buffer)的巧妙之處,也是寫緩存(Change Buffer)提高 MySQL
的地方。
Change Buffer 適用場景
Change Buffer 並不是適用於所有場景,以下兩種情況不適合開啟 Change Buffer :
- 1、數據庫都是唯一索引
如果數據庫都是唯一索引,那么在每次操作的時候都需要判斷索引是否有沖突,勢必要將數據加載到緩存中對比,因此也用不到 Change Buffer。
- 2、寫入一個數據后,會立刻讀取它
寫入一個數據后,會立刻讀取它,那么即使滿足了條件,將更新先記錄在 change buffer,但之后由於馬上要訪問這個數據頁,會立即觸發 merge 過程。這樣隨機訪問 IO 的次數不會減少,反而增加了 change buffer 的維護代價。所以,對於這種業務模式來說,change buffer 反而起到了副作用。
以下幾種情況開啟 Change Buffer,會使得 MySQL 數據庫明顯提升:
- 1、數據庫大部分是非唯一索引
- 2、業務是寫多讀少
- 3、寫入數據之后並不會立即讀取它
總體來說 InnoDB 的寫緩存(Change Buffer)應用得當,會極大提高 MySQL 數據庫的性能,使用不恰當的話,可能會適得其反。
以上就是今天分享的內容,希望對您的學習或者工作有所幫助,如果您覺得文章不錯,歡迎點個贊和轉發,謝謝。
最后
目前互聯網上很多大佬都有 MySQL 相關文章,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。
歡迎掃碼關注微信公眾號:「互聯網平頭哥」,和平頭哥一起學習,一起進步。