天天看點

[MySQL學習] Innodb change buffer(1)之初識篇

從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大神部落格上扣的圖:

[MySQL學習] Innodb change buffer(1)之初識篇

另外,change buffer的資料實際上是在系統表空間ibdata中,對應的内部系統表名為sys_ibuf_table。是以change buffer也會存儲到磁盤。

[MySQL學習] Innodb change buffer(1)之初識篇

其中,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值也是對應的。

繼續閱讀