一 簡介:今天咱們來聊聊mysql的change buffer
二 詳細說明
1 +-change Buffer和數據頁一樣,也是物理頁的一個組成部分,數據結構也是一顆B+樹,這棵B+樹放在共享表空間中,默認ibdata1中。change buffer 寫入系統表空間機制應該和普通表的臟頁刷新到磁盤是相同的機制--Checkpoint機制
2 具體查看
show engines inndo status 過濾
Ibuf: size 1, free list len 14316, seg size 14318(插入緩沖區的總大小 頁的數量X16KB), 466174 merges(已經合並的meregs數量)
merged operations: insert 547399(插入記錄被merge的次數), delete mark 42008(刪除操作被merge的次數), delete 32055(更新操作被merge了多少次)
如果merges/merged的值等於3/1,則代表插入緩沖對於非聚集索引頁的IO請求大約降低了3倍
三 具體過程
通用操作
1 判斷目標數據頁是否在內存中 -> 在, 直接操作數據頁(更新,插入)
-> 不在,將操作緩沖到change buffer中>在下次進行操作這個數據頁時,數據頁讀入內存,進行操作數據頁(更新,插入)->寫事務日志
2 merge 觸發條件 >定期刷新 change buffer到ibdata中進行物理保存
1 當目標數據頁被讀取到內存時進行操作
2 master thread 每隔10s會進行操作
3 當mysql關閉時會觸發進行操作
3 change buffer備份
change buffer雖然是內存的空間,也會定期刷新到磁盤,保證數據安全
4 change buffer補充
1 插入更新刪除操作的輔助索引數的維護操作
2 本質是一個全局性的B+樹,存在於共享表空間中,也即是ibdata
3 當通過ibd文件恢復表數據時,如果插入緩沖還在ibdata中,可能導致check_table失敗.需要手動執行repire tablle
5 change buffer的相關參數
1 innodb_change_buffering 默認是all支持所有DML操作
2 innodb_change_buffer_max_size,默認是25,即緩沖池的1/4。最大可設置為50,采用默認即可
6 目的
減少了從內存讀取硬盤的隨機讀IO(數據頁)操作,redo log減少了隨機寫log操作
四 現實例子
1 舉個現實中的例子來做說明,我們去圖書館還書,對應圖書館來說,他是做了insert(增加)操作,管理員在1小時內接受了100本書,這時候他有2種做法把還回來的書歸位到書架上
1)每還回來一本書,根據這本書的編碼(書櫃區-排-號)把書送回架上
2)暫時不做歸位操作,先放到櫃面上,等不忙的時候,再把這些書按照書櫃區-排-號先排好,然后一次性歸位
用方法1,管理員需要進出(IO)藏書區100次,不停的登高爬低完成圖書歸位操作,累死累活,效率很差。
用方法2,管理員只需要進出(IO)藏書區1次,對同一個位置的書,不管多少,都只要爬一次樓梯,大大減輕了管理員的工作量。
所以圖書館都是按照方法2來做還書動作的。而且如果暫時不歸還,需要相應的櫃子進行保存,相當於數據庫的insert buffer
2 為什么對於非聚集索引(非唯一)的插入和更新有效?
還是用還書的例子來說,還一本書A到圖書館,管理員要判斷一下這本書是不是唯一的,他在櫃台上是看不到的,必須爬到指定位置去確認,這個過程其實已經產生了一次IO操作,相當於沒有節省任何操作。
所以這個buffer只能處理非唯一的插入,不要求判斷是否唯一。聚集索引就不用說了,它肯定是唯一的,mysql現在還只能通過主鍵聚集。
3 前面說到管理員圖書歸位的時候,他會選擇在“不忙的時候”再去做,優先處理前台退書操作,這個在MYSQL里面是這樣體現的:
1)每1秒,如果IO次數小於5,合並插入緩沖。
2)每10秒,IO次數小於200,合並最多5個插入緩沖。
五 適用場景
事務進行操作后不會立刻查看的場景(寫多讀少),因為如果立刻查看會頻繁的觸發merge
六 補充
1 看完了上面的優化措施,我們應當明白了一點,為什么mysql不提倡建立很多無用的索引,因為每個輔助索引都需要成本來維護,雖然有了change buffer,還應該盡量避免建立無序索引
2 對於innodb的恢復機制應該加上change buffer 最后為 change buffer+redo log+binlog
3 change buffer本身一個缺點是可能會造成更多的內存占用,導致整個buffer_pool增大
