從mysql5.5版本開始,insert buffer更名為change buffer,除了緩沖對二級索引的insert操作,還包括update/delete/背景purge操作,由參數innodb_change_buffering來控制。是以這裡統一稱為change buffer。
//////////////////////////////////////////////////////////
當更新/插入的非聚集索引的資料所對應的頁不在記憶體中時(對非聚集索引的更新操作通常會帶來随機io),會将其放到一個insert buffer中,當随後頁面被讀到記憶體中時,會将這些變化的記錄merge到頁中。當伺服器比較空閑時,背景線程也會做merge操作
但change buffer會占用buffer pool,并且在非聚集索引很少時,并不總是必要的,反而會降低buffer pool做data cache的能力。
change buffer隻作用于二級索引的葉子節點,并且無法處理可能導緻索引分裂或合并的操作。
另外和5.1有所不同的是,由于5.5引入了更多buffer的操作,是以需要在ibuf中保證對一個page的操作是有序的。
當檔案頁在buffer pool中時,就直接操作檔案頁,而不會去考慮ibuf;當檔案頁從磁盤讀入記憶體時,總會去嘗試做merge。
在表空間中,有ibuf bitmap來跟蹤記錄每個page空閑空間的範圍,以避免page溢出或被清空。
在fsp_hdr頁随後是ibuf_bitmap頁,其中fsp_hdr在表空間的第一個page上。每個fsp_hdr隻能管理256 個extent的資訊(也就是16384個page),是以每隔16384個page,會有一個類似fsp_hdr的page來描述随後的extend資訊,相應的每個ibuf_bitmap也可以管理16384個page,每個page的空閑空間用一個位元組來表示。
從jeremy cole大神部落格上扣的圖:

另外,change buffer的資料實際上是在系統表空間ibdata中,對應的内部系統表名為sys_ibuf_table。是以change buffer也會存儲到磁盤。
其中,ibdata的第4個page(fsp_ibuf_header_page_no)存儲了ibuf數的segement資訊。
第5個page(fsp_ibuf_tree_root_page_no)是ibuf樹的根節點。
在percona版本的5.5中,有幾個參數來控制change buffer的行為:
innodb_change_buffering
取值包括all/none/inserts/deletes/changes/purges
其中deletes包括了delete和update操作(二級索引的update是
标記删除舊記錄,再插入新記錄).
innodb_ibuf_accel_rate
預設值為100,用于控制做change buffer merge的page數量
一般作為ibuf_contract_for_n_pages函數的第二個參數
是宏pct_ibuf_io,定義如下:
#define pct_ibuf_io(pct) ((ulint) (srv_io_capacity
* srv_ibuf_accel_rate * ((double) pct / 10000.0)))
如果想加快ibuf merge,可以調大這個參數
innodb_ibuf_active_contract
bool類型,預設值為0;
如果在執行ibuf_insert_low時,寫入ibuf記錄導緻ibuf tree分裂,
會去調用ibuf_contract_after_insert對ibuf進行merge。
預設值為0表示,如果目前ibuf的大小沒有超過最大值,則不做merge
設定為1則表示,每次出現ibuf tree分裂,都要去merge ibuf.
innodb_ibuf_max_size
change buffer的占buffer pool記憶體的最大值,預設為二分之一的
buffer pool大小。這是隻讀變量;如果使用change buffer,一定要
考慮這個值是否合适;
有一些變量可以來監控change buffer的運作狀态(内部變量見函數ibuf_export_ibuf_status):
innodb_ibuf_discarded_delete_marks
對應ibuf->n_discarded_ops[ibuf_op_delete_mark]
抛棄的delete mark操作次數
innodb_ibuf_discarded_deletes
ibuf->n_discarded_ops[ibuf_op_delete]
抛棄的purge delete記錄次數
innodb_ibuf_discarded_inserts
ibuf->n_discarded_ops[ibuf_op_insert]
抛棄的insert操作次數
innodb_ibuf_free_list
對應ibuf->free_list_len,表示ibuf樹的空閑連結清單長度,
innodb_ibuf_merged_delete_marks
ibuf->n_merged_ops[ibuf_op_delete_mark]
合并delete mark操作的次數
innodb_ibuf_merged_deletes
ibuf->n_merged_ops[ibuf_op_delete]
合并purge操作的次數
innodb_ibuf_merged_inserts
ibuf->n_merged_ops[ibuf_op_insert]
合并insert操作的次數
innodb_ibuf_merges
ibuf->n_merges
總的合并次數
innodb_ibuf_segment_size
ibuf->seg_size 包含ibuf header頁和ibuf tree的segment的page數
innodb_ibuf_size
ibuf->size 表示ibuf 索引樹的page數
其中
ibuf->size = ibuf->seg_size – (1 + ibuf->free_list_len)
ibuf->free_list_len = flst_get_len(root + page_header+ page_btr_ibuf_free_list, mtr); //root為ibuf樹的根頁面
ibuf是一個全局變量,也是change buffer的控制結構體,其對應的結構體類型為ibuf_struct,可以看到其中大部分記錄的都是計數,用于追蹤ibuf樹
目前的狀态,以内記憶體changebuffer操作的計數,除了上面提到的幾個結構體成員外,還有:
ibook empty; //當為true時,表示ibuf樹為空,該變量由ibuf根頁面的page latch保護。
ulint height; //ibuf樹的高度
dict_index_t* index; //ibuf數上的索引結構體。
另外show engine innodb status也會列印一些相關資訊:
————————————-
insert buffer and adaptive hash index
ibuf: size 1, free list len 1886, seg size 1888, 7176 merges
merged operations:
insert 9747, delete mark 18295, delete 13183
discarded operations:
insert 0, delete mark 0, delete 0
這些值和上面提到的幾個status值也是對應的。