主頁(yè) > 知識(shí)庫(kù) > MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)

MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)

熱門(mén)標(biāo)簽:武漢電銷(xiāo)機(jī)器人電話 大豐地圖標(biāo)注app 400電話辦理服務(wù)價(jià)格最實(shí)惠 北京金倫外呼系統(tǒng) html地圖標(biāo)注并導(dǎo)航 400電話變更申請(qǐng) 呂梁外呼系統(tǒng) 催天下外呼系統(tǒng) 南太平洋地圖標(biāo)注

什么是insert buffer?

   插入緩沖,也稱(chēng)之為insert buffer,它是innodb存儲(chǔ)引擎的關(guān)鍵特性之一,我們經(jīng)常會(huì)理解插入緩沖時(shí)緩沖池的一個(gè)部分,這樣的理解是片面的,insert buffer的信息一部分在內(nèi)存中,另外一部分像數(shù)據(jù)頁(yè)一樣,存在于物理頁(yè)中。

    在innodb中,我們知道,如果一個(gè)表有自增主鍵,那么對(duì)于這個(gè)表的默認(rèn)插入是非常快的,注意,這里的主鍵是自增的,如果不是自增的,那么這個(gè)插入將會(huì)變成隨機(jī)的,就可能帶來(lái)數(shù)據(jù)頁(yè)分裂的開(kāi)銷(xiāo),這樣,插入就不是順序的,就會(huì)變慢。還有一種情況,就是如果我們插入的id不是順序的,而是隨機(jī)的,那么即使有自增主鍵,那么插入的速度也不會(huì)特別快。

    如果我們定義了一個(gè)表,包含一個(gè)主鍵和一個(gè)非聚集索引,如下:

create table t(

a int auto_increment,

b varchar(30),

primary key(a),

key (b)

);

當(dāng)我們按照主鍵a進(jìn)行插入的時(shí)候,對(duì)于非聚集索引,也就是常說(shuō)的二級(jí)索引b,它的插入不是順序的,插入性能必然會(huì)下降。

  Innodb存儲(chǔ)引擎針對(duì)這種情況,設(shè)計(jì)了Insert Buffer,對(duì)于非聚集索引的插入或者更新操作,不是每一次插入到索引頁(yè)中,而是先判斷插入的非聚集索引頁(yè)是否在緩沖池中,如果在,則直接插入,如果不在,則先放入一個(gè)insert buffer中,告訴數(shù)據(jù)庫(kù)這個(gè)非聚集的索引已經(jīng)插入到了葉子節(jié)點(diǎn),實(shí)際上并沒(méi)有插入,只是存放在另外一個(gè)位置,然后再以一定的頻率和情況進(jìn)行Insert buffer和輔助索引葉子節(jié)點(diǎn)合并操作。這種時(shí)候,經(jīng)常能將多條記錄的插入合并到一個(gè)操作中,這樣就大大提高了非聚集索引離散插入的性能。

insert buffer的觸發(fā)條件?

    insert buffer需要滿足兩個(gè)條件才能被使用,第一,索引是輔助索引,也就是二級(jí)索引,第二,索引不是唯一的。當(dāng)滿足上述兩個(gè)條件的時(shí)候,就可以使用insert buffer,從而提高數(shù)據(jù)庫(kù)的插入操作性能。

    這里需要注意,如果在程序進(jìn)行了大量操作的時(shí)候發(fā)生了MySQL數(shù)據(jù)庫(kù)的宕機(jī),那么肯定有大量的insert buffer沒(méi)有合并到實(shí)際的非聚集索引中去,恢復(fù)可能會(huì)造成很長(zhǎng)的時(shí)間。

為什么不能是唯一索引?

    之所以不支持唯一索引,是因?yàn)槿绻o助索引是唯一索引,那么在插入時(shí)需要校驗(yàn)唯一性,校驗(yàn)唯一性的時(shí)候就會(huì)發(fā)生離散讀取,從而又增加了開(kāi)銷(xiāo),那么insert buffer得不償失。

    我們可以通過(guò)show engine innodb status來(lái)查看insert buffer的使用情況,如下:

mysql--root@localhost:dms_alimetadata 20:35:24>>show engine innodb status\G
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0

  其中size代表了已經(jīng)合并記錄頁(yè)的數(shù)量,free list len代表了空閑列表的長(zhǎng)度,seg size顯示了當(dāng)前insert buffer的大小為2*16KB

引入Change Buffer的概念

    最新的MySQL5.7已經(jīng)支持change buffer,事實(shí)上,它在innodb 1.0.x版本已經(jīng)引入,這個(gè)change buffer 可以理解為insert buffer的升級(jí),也就是對(duì)常見(jiàn)的DML語(yǔ)言都可以進(jìn)行緩沖,包含insert delete以及update,對(duì)應(yīng)的分別是insert buffer,delete buffer以及purge buffer。

   當(dāng)然,change buffer的使用對(duì)象仍然是非唯一的輔助索引。

    這里我們以u(píng)pdate操作為例,update的過(guò)程可以拆分為兩個(gè)部分:

第一個(gè)部分是將記錄的delete_mask標(biāo)記為刪除,如果你不了解delete_mask,可以在4月9號(hào)的文章中去看。第二個(gè)部分是真正的將記錄刪除。

而delete buffer對(duì)應(yīng)的是update的第一個(gè)過(guò)程,purge buffer對(duì)應(yīng)的是第二個(gè)部分。

    在innodb中,我們可以通過(guò)參數(shù)innodb_change_buffering來(lái)開(kāi)啟buffer的各種選項(xiàng),該參數(shù)可選的值為inserts,deletes,purges,changes,all,none等,其中inserts,deletes和purges就是前面討論過(guò)的情況,changes表示開(kāi)啟inserts和deletes,all表示開(kāi)啟所有,默認(rèn)的參數(shù)如下:

mysql--root@localhost:dms_alimetadata 21:13:37>>show variables like '%buffering%';        
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_change_buffering | all   |
+-------------------------+-------+
1 row in set (0.01 sec)

我們還可以通過(guò)innodb_change_buffer_max_size來(lái)控制change_buffer的最大使用內(nèi)存數(shù)量,該參數(shù)的默認(rèn)值是25,也就是1/4,示例如下:

mysql--root@localhost:dms_alimetadata 21:20:52>>show variables like '%innodb_change_buffer_max_size%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_change_buffer_max_size | 25    |
+-------------------------------+-------+
1 row in set (0.00 sec)

    在上面的show engine innodb status命令的輸出結(jié)果中,顯示了merged operation和discarded operation,其中insert 表示insert buffer的操作次數(shù),delete mark表示delete buffer的操作次數(shù),而delete表示purge buffer的操作次數(shù),discarded operation表示當(dāng)change buffer發(fā)生merge時(shí),表已經(jīng)被刪除,此時(shí)就無(wú)需進(jìn)行合并。

Insert Buffer的實(shí)現(xiàn)?

   insert buffer的數(shù)據(jù)結(jié)構(gòu)是一棵B+樹(shù),類(lèi)似聚集索引一樣,全局只有一棵insert buffer B+樹(shù),它負(fù)責(zé)對(duì)所有的表進(jìn)行insert buffer,而這棵B+樹(shù)放在共享表空間中,也就是ibdata1文件中,因此,試圖通過(guò)ibd文件恢復(fù)表數(shù)據(jù)的時(shí)候可能會(huì)出現(xiàn)check table失敗,原因是表的輔助索引中的數(shù)據(jù)可能還在insert buffer中,所以通過(guò)ibd文件恢復(fù)文件之后,還需要進(jìn)行repair table操作來(lái)重建表上的輔助索引。

   insert buffer既然是一棵樹(shù),那么必定有葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn),非葉子節(jié)點(diǎn)存放的是查詢(xún)的search key值,它的構(gòu)造如下:

+---------+------------+-------+
| space   |   marker   | Value |
+---------+------------+-------+

這個(gè)結(jié)構(gòu)一共占用9個(gè)字節(jié),其中,space表示待插入的記錄所在的表的表空間id,這個(gè)id是每個(gè)表都要有的唯一的id,其中space占用4個(gè)字節(jié),marker占用1個(gè)字節(jié),用來(lái)兼容老版本的insert buffer,offset占用4個(gè)字節(jié),表示頁(yè)所在的偏移量。

輔助索引的插入過(guò)程?

    當(dāng)一個(gè)輔助索引要插入到數(shù)據(jù)頁(yè)的時(shí)候,如果這個(gè)數(shù)據(jù)頁(yè)不在緩沖池中,那么innodb會(huì)根據(jù)規(guī)則構(gòu)造一個(gè)search key,接下來(lái)將這個(gè)記錄插入到insert buffer的B+樹(shù)里面去,插入的過(guò)程中,需要對(duì)這個(gè)記錄進(jìn)行一些構(gòu)造,最終插入的結(jié)果是類(lèi)似下面這樣的一條記錄:

+---------+------------+-------+------------+------+-------+------+-------+
| space   |   marker   | Value | metadata   |      |       |      |       |
+---------+------------+-------+------------+------+-------+------+-------+

可以發(fā)現(xiàn),最后面多了一個(gè)metadata的字段和4個(gè)其他的字段,先來(lái)說(shuō)說(shuō)metadata的字段,它占用4個(gè)字節(jié),它用來(lái)排序每個(gè)記錄進(jìn)入insert buffer的順序,從第5列開(kāi)始,就是實(shí)際插入記錄的各個(gè)字段的值了,因此和單純的數(shù)據(jù)記錄相比,insert buffer需要額外13個(gè)字節(jié)的開(kāi)銷(xiāo)。

   為了保證每次merge insert buffer成功,需要設(shè)置一個(gè)特殊的數(shù)據(jù)頁(yè)來(lái)標(biāo)記每個(gè)輔助索引頁(yè)的可用空間,這個(gè)數(shù)據(jù)頁(yè)的類(lèi)型為insert buffer bitmap,這個(gè)頁(yè)可以追蹤很多輔助索引頁(yè)的可用空間。這里簡(jiǎn)單了解一下,下面會(huì)解釋它的用法。

Merged Insert Buffer的時(shí)機(jī)?

   我們前面已經(jīng)知道,當(dāng)插入記錄的輔助索引頁(yè)不在緩沖池中的時(shí)候,需要將輔助索引記錄插入到這棵B+樹(shù)中,后續(xù)會(huì)從insert buffer中往真正的輔助索引中進(jìn)行合并,那么什么時(shí)候進(jìn)行合并呢?

1、輔助索引頁(yè)被讀取到緩沖池的時(shí)候

2、insert buffer Bitmap追蹤到該輔助索引頁(yè)已經(jīng)沒(méi)有足夠的可用空間時(shí),一般的閾值是輔助索引頁(yè)空間的1/32

3、master thread每秒執(zhí)行一次merge insert buffer的操作

以上就是MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)的詳細(xì)內(nèi)容,更多關(guān)于Innodb特性之插入緩沖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • MySQL InnoDB架構(gòu)的相關(guān)總結(jié)
  • MySQL InnoDB ReplicaSet(副本集)簡(jiǎn)單介紹
  • 詳解MySQL InnoDB存儲(chǔ)引擎的內(nèi)存管理
  • MySQL InnoDB 鎖的相關(guān)總結(jié)
  • 如何區(qū)分MySQL的innodb_flush_log_at_trx_commit和sync_binlog
  • Mysql InnoDB的鎖定機(jī)制實(shí)例詳解
  • Mysql技術(shù)內(nèi)幕之InnoDB鎖的深入講解
  • 修改MySQL數(shù)據(jù)庫(kù)引擎為InnoDB的操作
  • 簡(jiǎn)述MySQL InnoDB存儲(chǔ)引擎
  • MySQL InnoDB表空間加密示例詳解
  • MySQL InnoDB 事務(wù)鎖源碼分析

標(biāo)簽:徐州 西寧 麗水 龍巖 迪慶 南充 自貢 無(wú)錫

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)》,本文關(guān)鍵詞  MySQL,Innodb,關(guān)鍵,特性,之,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于MySQL Innodb關(guān)鍵特性之插入緩沖(insert buffer)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章