InnoDB概念

MySQL是當前最流行的關(guān)系型數(shù)據(jù)庫。MySQL的體系架構(gòu)如下圖所示:
MySQL架構(gòu)

MySQL架構(gòu):

  • Connectors:MySQL向外提供的交互接口:

    Java等語言可以通過該接口實現(xiàn)和SQL的交互萧吠,操作SQL語句。

  • Management Service & Utilities:管理服務(wù)組件和工具組件:

    提供對MySQL的集成管理中鼠,包括:備份色难,恢復,安全管理等躁绸。

  • Connection Pool:連接池組件:

    負責監(jiān)聽客戶端到MySQL的請求裕循,創(chuàng)建線程負責之間的通信。

  • SQL Interface:SQL接口組件:

    接收客戶端的SQL命令净刮,將結(jié)果返回客戶端剥哑。

  • Parser:查詢分析器組件:

    分析SQL的合法性,并解析SQL的數(shù)據(jù)結(jié)構(gòu)淹父。

  • Optimizer:優(yōu)化器組件:

    對SQL進行優(yōu)化分析株婴。

  • Caches & Buffers:緩存組件:

    SQL結(jié)果等緩存。

  • Pluggable Storage Engine:插拔式存儲引擎:

    可插拔式的存儲引擎暑认,用于表的創(chuàng)建困介,數(shù)據(jù)檢索,索引創(chuàng)建等蘸际;也可滿足自定義的存儲引擎開發(fā)座哩。

  • File System:物理文件:

    實際存儲數(shù)據(jù)的文件。

  • Files & Logs:文件和日志:

    存儲各式各樣的日志文件粮彤。

其中MySQL的關(guān)鍵特點就是可插拔的存儲引擎根穷;其中InnoDB是MySQL的默認存儲引擎,也是應(yīng)用最為廣泛的存儲存儲引擎导坟,本文主要介紹InnoDB存儲引擎的關(guān)鍵特性以及這些特性的一些思考屿良。

數(shù)據(jù)庫和數(shù)據(jù)實例的區(qū)別:

  • 數(shù)據(jù)庫是文件的集合,是依照某種數(shù)據(jù)模型組織起來并存放于二級存儲器中的數(shù)據(jù)集合惫周;
  • 數(shù)據(jù)庫實例是程序管引,是位于用戶與操作系統(tǒng)之間的一層數(shù)據(jù)管理軟件;

InnoDB關(guān)鍵特性

InnoDB有以下關(guān)鍵特性闯两,其中前三個是數(shù)據(jù)庫最通用的特性:

  • Change Buffer(寫緩存)

  • Double Write(二次寫)

  • Adaptive Hash Index(自適應(yīng)哈希索引)

  • Async IO(異步IO)

  • Flush Neighbor Page(屬性鄰接頁)

1. Change Buffer

Change Buffer是InnoDB中最特殊的一個特性。Change Buffer是從InnoDB 1.0.x版本之后的引入的概念谅将,在1.0.x版本之前叫Insert Buffer(插入緩存)漾狼。Insert Buffer顧名思義是針對Insert的緩存。

1.1 問題誕生背景

對于InnoDB饥臂,所有的數(shù)據(jù)逊躁,索引等都是以文件的形式存儲,以B+樹的形式存儲隅熙。 InnoDB的索引分為兩種:聚簇索引(Primary Index)和非聚簇索引(Secondary Index)稽煤;其中聚簇索引的B+樹葉子節(jié)點存放的是真實的數(shù)據(jù)核芽;而非聚簇索引的葉子節(jié)點存放的是聚簇索引的主鍵值。

我們先從索引的角度來描述下問題的背景:

  • 對于聚簇索引酵熙,主鍵是唯一的轧简;當插入新的數(shù)據(jù)時,需要檢查下磁盤是否有主鍵沖突匾二,這步磁盤訪問必不可少哮独;此外,一般對于主鍵的插入是順序的(比如id自增列)察藐,這樣磁盤是順序讀寫的皮璧,有較好的性能。

  • 對于非聚簇索引分飞,列值不唯一悴务;當插入新的數(shù)據(jù)時,插入的數(shù)據(jù)很難是按遞增的順序插入的譬猫,這時候?qū)τ诓迦氩僮鞫际请S機的讯檐;如果有大量的插入操作,則會有大量的隨機IO删窒,會嚴重影響磁盤的性能裂垦。

因此Insert Buffer誕生的問題背景是: 大量的非聚簇索引插入操作?肌索?蕉拢?

產(chǎn)生的問題背景也反映了Insert Buffer需要滿足兩點:

  • 必須是非聚簇索引;

  • 索引的數(shù)據(jù)不是唯一的诚亚;(后面也會有介紹)

1.2 內(nèi)部實現(xiàn)

  1. MySQL數(shù)據(jù)存儲包含內(nèi)存和磁盤兩部分晕换;
  1. 內(nèi)存緩沖池以頁(Page)為單位,緩存最熱的是:數(shù)據(jù)頁和索引頁站宗;
  1. InnoDB以變種LRU(加了mid位置和時間的概念闸准,非常類似于JVM的內(nèi)存管理)的算法來管理緩沖池,解決了“預(yù)讀失效”和“緩沖池污染”的問題梢灭;

(1)情況一 當要插入的數(shù)據(jù)已經(jīng)在緩沖池了夷家,則只需要插入redo日志文件一次磁盤操作;但redo的磁盤是順序?qū)懨羰停屎芨呖饪欤灰虼诉@種情況不需要Insert Buffer。

緩沖池會定期的刷新到磁盤上钥顽,而不是每次都刷新义屏,這樣會降低磁盤的IO,提升性能,說白了就是批量寫(可能會有同一個數(shù)據(jù)頁的合并操作)闽铐。

(2)情況二 當要插入的數(shù)據(jù)不再緩沖池中蝶怔,這時候需要怎么辦? 為了避免大量的隨機IO兄墅,提出了Insert Buffer的概念踢星;當插入數(shù)據(jù)時,先把數(shù)據(jù)插入到Insert Buffer中察迟;當需要回刷磁盤時斩狱,會把Insert Buffer中的數(shù)據(jù)進行merge后寫入磁盤(因為有merge,為了表示現(xiàn)有頁的空閑空間扎瓶,還需要一個特殊的頁來保存每個非聚簇索引頁的空閑空間)所踊,降低了磁盤隨機IO。Insert Buffer也是B+樹的結(jié)構(gòu)概荷,插入數(shù)據(jù)時也是按照頁來組織聚簇索引和非聚簇索引數(shù)據(jù)秕岛。

舉個形象的例子來說明Insert Buffer的具體作用: 圖書管理員進行書籍整理,有兩種做法:

  • 每歸還一本書误证,就去對應(yīng)的書架上歸還這本書继薛;

  • 先把書放在柜臺,等書達到一定量的時候愈捅,進行批量的放回對應(yīng)的書架遏考;

正常人都會選擇第二種做法;而柜臺就是Insert Buffer蓝谨,歸還的書會先在柜臺上進行整理灌具,合并,然后一起放回書架譬巫,減少了書架的隨機訪問咖楣。

在MySQL5.5之后,不僅針對insert操作芦昔,還針對update和delete操作诱贿,改名為Change Buffer,原理是一致的。

Change Buffer還有一個細節(jié)點咕缎,當Change Buffer中的有數(shù)據(jù)沒有寫到磁盤前珠十,數(shù)據(jù)庫宕機了,這個時候Change Buffer的數(shù)據(jù)就恢復不了了凭豪,因此鑒于這種情況宵睦,InnoDB會把Change Buffer中的數(shù)據(jù)定期通過merge操作刷回表空間中的索引文件。

Change Buffer結(jié)構(gòu)圖:
Change Buffer

從圖中可以看出墅诡,Change Buffer并不僅僅指的是內(nèi)存中的一塊,還包含了物理磁盤上的共享表空間。

1.3 缺點

  • 如果有大量的DML變更操作末早,數(shù)據(jù)宕機后烟馅,會導致恢復的時間較長;

  • 有大量插入的時候然磷,會導致占用較多的Buffer Pool內(nèi)存郑趁,會影響其他數(shù)據(jù)的空間;

  • 對于不同的硬件配置和負載姿搜,Change Buffer無法進行控制寡润,比如磁盤和SSD;

2. Double Write

從IO的角度來看舅柜,InnoDB是以頁為維度來讀取數(shù)據(jù)梭纹,正常InnoDB的頁可以配置為4K,8K致份,16K;而文件系統(tǒng)的IO讀寫最小單位是4K变抽,也有些是1K;磁盤的讀寫最小單位是扇區(qū)(512KB)氮块。

由于各系統(tǒng)以及硬件IO讀寫的單位不一致绍载,往往底層的單位要小于上層的單位,因此上層就會存在部分寫的場景:當寫一部分數(shù)據(jù)的時候滔蝉,機器宕機了击儡,這樣就會導致部分寫的場景。(磁盤是由硬件保證蝠引,要么512KB全部寫成功阳谍,要么都失敗,不存在部分寫的場景)

2.1 問題誕生背景

由上述知道立肘,InnoDB的IO最小單位是頁,正常大小為16K(可以配置為4K边坤,8K等);當緩沖池中的臟頁回寫磁盤時谅年,磁盤的頁和緩沖池的頁是對等的茧痒,也就是要回寫16K的數(shù)據(jù)到磁盤;而文件系統(tǒng)的讀寫單位可能是4K融蹂;這樣就需要寫入4次旺订,才能完整的把臟頁刷回去;如果在寫2次的時候超燃,機器斷電宕機了区拳,這個時候磁盤的頁就被污染了。

基于這種場景意乓,InnoDB誕生了Double Write的特性樱调,用于解決partial page write(部分寫)的問題。

2.2 內(nèi)部實現(xiàn)

參考Change Buffer的設(shè)計,Double Write也在Buffer Pool中開辟一塊內(nèi)存笆凌,用來存放修改的臟頁圣猎;并在磁盤的共享表中間中存放臟頁,Double Write的邏輯如下圖所示:
Double Write

Double Write的步驟:

  1. 當觸發(fā)臟頁刷新時乞而,先把臟頁拷貝到Double Write內(nèi)存中送悔;

  2. 接著把Double Write中的臟頁順序的寫到共享表空間中,這部分是順序?qū)懭氪疟P爪模,性能很高欠啤;

  3. 異步的將共享表空間的數(shù)據(jù)離散的寫入到各個表空間中;

Double Write如何宕機恢復的屋灌??声滥?

  • 如果寫入Double Write Buffer時失敗眉撵,這個時候頁還沒有刷新回磁盤,也就沒有發(fā)生部分寫的問題落塑,因此直接從磁盤加載原始數(shù)據(jù)纽疟,并通過事務(wù)日志重新計算寫入Double Write Buffer。

  • 如果寫入磁盤時憾赁,宕機污朽,由于共享表空間中副本數(shù)據(jù)恢復,重新寫入磁盤即可龙考。

為啥不用redo log解決部分寫的問題蟆肆??晦款? 這個涉及到redo log的數(shù)據(jù)設(shè)計炎功;如果redo log中保存了所有的數(shù)據(jù)和操作,那么redo log的size會非常大缓溅,不利于日志文件存儲蛇损;因此InnoDB對于redo log的設(shè)計是保存頁的指針之類的數(shù)據(jù);因此redo log無法恢復物理頁坛怪,因為redo log中不保存真實的數(shù)據(jù)淤齐。

2.3 缺點

雖然共享表空間的寫入是磁盤順序?qū)懀廊粫绊慚ySQL的性能袜匿;尤其是InnoDB為了保證寫入共享表空間數(shù)據(jù)的完整性更啄,在每次寫入后都會調(diào)用fsync操作等待磁盤操作結(jié)束,硬盤的fsync性能比較慢居灯;

3. Adaptive Hash Index

自適應(yīng)哈希索引是InnoDB內(nèi)部的一個優(yōu)化特性祭务,一般不需要開發(fā)人員關(guān)注内狗。

3.1 問題誕生背景

首先了解下InnoDB的數(shù)據(jù)存儲,InnoDB的數(shù)據(jù)和主鍵索引一起存儲义锥,主鍵索引的葉子節(jié)點存放的是數(shù)據(jù)其屏;非主鍵索引葉子節(jié)點存放的是主鍵的key值。

當通過非聚簇索引來查詢數(shù)據(jù)時缨该,根據(jù)B+索引樹查詢?nèi)~子節(jié)點的主鍵key,然后根據(jù)主鍵key再去主鍵索引的B+樹上找到對應(yīng)的葉子節(jié)點的數(shù)據(jù)。

可以看出來通過非聚簇索引來查詢數(shù)據(jù)時川背,需要訪問兩個B+樹贰拿,而自適應(yīng)哈希索引就是為了解決這個問題,直接構(gòu)造非聚簇索引key到真實數(shù)據(jù)的哈希索引熄云,哈希的時間復雜度是O(1)膨更;因此減少了兩次B+樹的查詢操作。

自適應(yīng)哈希索引是索引的索引 =稍省<允亍!

3.2 內(nèi)部實現(xiàn)

自適應(yīng)哈希索引的難點在于信息統(tǒng)計练般,要統(tǒng)計出查詢的熱點數(shù)據(jù)矗漾,為這些熱點數(shù)據(jù)建立哈希索引。比如對于同一條件的頻繁訪問薄料,可以構(gòu)造出哈希索引敞贡,下次同樣的條件可以直接獲取結(jié)果。

自適應(yīng)哈希索引的結(jié)構(gòu)如下圖所示:
自適應(yīng)哈希索引

自適應(yīng)哈希索引實現(xiàn)的條件:

  1. 精確條件查詢摄职,以該條件查詢超過100次誊役;

  2. 頁訪問的次數(shù)N=頁記錄數(shù)/16; (內(nèi)部具體的信息統(tǒng)計涉及很多參數(shù)谷市,后續(xù)分析)

3.3 缺點

  1. 自適應(yīng)哈希索引也是占用Buffer Pool的空間蛔垢,會影響其他類型數(shù)據(jù)的空間容量;

  2. 自適應(yīng)哈希索引只支持精確條件查詢迫悠,不支持范圍查找鹏漆;

  3. 自適應(yīng)哈希索引只有在極端的情況下(大量固定條件的查詢),才有意義及皂,降低邏輯讀時間甫男;

4. Async IO

為了提供磁盤操作性能,現(xiàn)在的數(shù)據(jù)庫系統(tǒng)都是采用異步IO的方式來處理磁盤操作验烧。異步IO還支持批量操作板驳,把多個頁進行整合一起進行IO操作,如果是同一頁的數(shù)據(jù)碍拆,或者連續(xù)的數(shù)據(jù)若治,會提高磁盤的IO性能慨蓝。

5. Flush Neighbor Page

刷新鄰接頁是根據(jù)“局部性”原理,其工作原理是: 當刷新一個臟頁時端幼,InnoDB存儲引擎會檢測該頁所在區(qū)(extent)的所有頁礼烈,如果是臟頁,那么一起進行刷新婆跑。這樣做的好處顯而易見此熬,通過AIO可以將多個IO寫入操作合并為一個IO操作,故該工作機制在傳統(tǒng)機械磁盤下有著顯著的優(yōu)勢滑进。

InnoDB文件的格式是idb后綴犀忱,其中存放了表的數(shù)據(jù),又稱為表空間Tablespace扶关,表空間又分為多個段Segment阴汇;一個Segment又分為多個區(qū)Extent;一個區(qū)又分為多個頁Page节槐;一個頁包含了多個行Row搀庶。

后記

InnoDB的關(guān)鍵特性和文件的存儲結(jié)果密切相關(guān),后面會分析下InnoDB表數(shù)據(jù)的文件存儲結(jié)構(gòu)铜异。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哥倔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子熙掺,更是在濱河造成了極大的恐慌未斑,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件币绩,死亡現(xiàn)場離奇詭異蜡秽,居然都是意外死亡,警方通過查閱死者的電腦和手機缆镣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門芽突,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人董瞻,你說我怎么就攤上這事寞蚌。” “怎么了钠糊?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵挟秤,是天一觀的道長。 經(jīng)常有香客問我抄伍,道長艘刚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任截珍,我火速辦了婚禮攀甚,結(jié)果婚禮上箩朴,老公的妹妹穿的比我還像新娘。我一直安慰自己秋度,他們只是感情好炸庞,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荚斯,像睡著了一般埠居。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上事期,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天拐格,我揣著相機與錄音,去河邊找鬼刑赶。 笑死,一個胖子當著我的面吹牛懂衩,可吹牛的內(nèi)容都是我干的撞叨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浊洞,長吁一口氣:“原來是場噩夢啊……” “哼牵敷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起法希,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤枷餐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后苫亦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毛肋,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年屋剑,在試婚紗的時候發(fā)現(xiàn)自己被綠了润匙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡唉匾,死狀恐怖孕讳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情巍膘,我是刑警寧澤厂财,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站峡懈,受9級特大地震影響璃饱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜逮诲,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一帜平、第九天 我趴在偏房一處隱蔽的房頂上張望幽告。 院中可真熱鬧,春花似錦裆甩、人聲如沸冗锁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冻河。三九已至,卻和暖如春茉帅,著一層夾襖步出監(jiān)牢的瞬間叨叙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工堪澎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留擂错,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓樱蛤,卻偏偏與公主長得像钮呀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昨凡,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354