InnoDB Insert Buffer(插入緩沖)
InnoDB Insert Buffer(插入緩沖)
每個存儲存儲引擎自身都有自己的特性(決定性能以及更高可靠性),而InnoDB的關鍵特性有:
- 插入緩沖(Insert Buffer)--》Change Buffer
- 兩次寫(Double Write)
- 自適應哈希索引(Adaptive Hash Page)
- 異步IO(Async IO)
- 刷新鄰接頁(Flush Neighbor Page)
今天主要聊一下插入緩沖(Insert Buffer)在InnoDB存儲引擎中的作用。
Insert Buffer其實是一種重要的數據變更日誌,在MySQL5.1 之前稱為Insert Buffer, 優化2級非唯一索引上插入操作的讀IO,在MySQL5.5之後改名為Change Buffer, 功能也擴展為2級非唯一索引上的插入、刪除、更新、purge的讀IO優化。也就是說Change buffer的主要目的是將對二級索引的數據操作緩存下來,以此減少二級索引的隨機IO,並達到操作合並的效果。值得提的一點是,Change Buffer也是物理頁的組成部分。
struct ibuf_struct{ ulint size; //當前ibuf btree 頁面數 ulint max_size; //ibuf最大頁面數 ulint seg_size; //所屬段的頁面數ibool empty; //是否為空 ulint free_list_len; //空閑鏈表長度 ulint height; //樹高度 dict_index_t* index; //ibuf索引 ulint n_merges; //合並的頁面數 ulint n_merged_ops[IBUF_OP_COUNT]; //各種操作合並的頁面數 ulint n_discarded_ops[IBUF_OP_COUNT]; //放棄的操作涉及的頁面數 };
從上述的結構體可以得知,Ibuf實際上也是一棵B+樹索引,它與innodb中其他的b+樹有著完全一樣的結構。Ibuf樹中的記錄其實就是包含了記錄本身,還有記錄所在頁面號的信息。
值得註意的點是,ibuf只適用於 non-unique secondary indexes 也就是說只能用在非唯一的索引上,原因如下:
1. primary key 是按照遞增的順序進行插入的,異常插入聚族索引一般也順序的,非隨機IO
2. 寫唯一索引要檢查記錄是不是存在,所以在修改唯一索引之前,必須把修改的記錄相關的索引頁讀出來才知道是不是唯一、這樣ibuf就沒意義了,要讀出來(隨機IO)所以只對非唯一索引有意義。
ibuf可以對三種類型的操作進行緩存:INSERT、DELETE-MARK 、DELETE操作,前兩種對應用戶線程操作,第三種則由purge操作觸發。
用戶可以通過參數innodb_change_buffering來控制緩存何種操作:
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = { "none", /* IBUF_USE_NONE */ "inserts", /* IBUF_USE_INSERT */ "deletes", /* IBUF_USE_DELETE_MARK */ "changes", /* IBUF_USE_INSERT_DELETE_MARK */ "purges", /* IBUF_USE_DELETE */ "all" /* IBUF_USE_ALL */ };
ibuf默認值為all,表示緩存所有操作。註意由於在二級索引上的更新操作總是先delete-mark,再insert新記錄,因此update會產生兩條ibuf entry。
因此delete buffer對應update操作的第一個過程,即將記錄標記為刪除。purge buffer對應update操作的第二個過程,即將記錄真正的刪除。同時InnoDB存儲引擎提供了參數innodb_change_buffering,用來開啟各種buffer選項。該參數的可選值為:inserts、deletes、purges、changes、all、none。inserts、deletes、purges就是前面討論過的三種情況。changes表示啟用inserts和deletes,all表示啟用所有,none表示都不啟用。
InnoDB Insert Buffer(插入緩沖)