InnoDB存儲引擎(一)概述

1、概述

InnoDB是事務安全的MySQL存儲引擎,支持ACID,他的特點是:

  • 行鎖設計
  • 支持外鍵
  • 提供一致性非鎖定讀
  • 支持MVCC

2、InnoDB體系架構

InnoDB存儲引擎主要由後臺線程和內存塊構成,可以認爲這些內存塊組成了一個大的內存池,負責如下工作:

  • 維護所有進程/線程需要訪問的多個數據結構
  • 維護磁盤上的數據,方便快速讀取
  • 在數據刷到磁盤前緩存數據
  • 重做日誌(redo log)緩衝

2.1 後臺線程

2.1.1 Master Thread

這是核心的後臺線程,主要負責將緩衝池中的數據異步刷新到磁盤,保證數據的一致性

  • 髒頁的刷新
  • 合併插入緩衝
  • undo頁的回收
2.1.2 IO Thread

InnoDB中用了大量AIO來處理寫IO請求,而IO Thread用來處理這些IO請求的回調。InnoDB1.0版本之前有4個IO Thread,分別是write,read,insert buffer,log

2.1.3 Purge Thread

事務Commit後undolog可能不再需要,該線程主要用來回收undo頁

2.1.4 Page Cleaner Thread

將之前版本中髒頁的刷新操作都放入這個線程中去處理,減輕Master Thread的負擔

2.2 內存

2.1.1 緩衝池

InnoDB存儲引擎是基於磁盤存儲的,其中記錄以頁的方式管理。
緩衝池簡單來說就是一塊內存區域,協調CPU速度與磁盤速度的鴻溝。
緩衝池的作用、特點:

  • 讀操作,從磁盤上讀頁載入緩衝池,下次再讀相同頁,直接從內存中取。
  • 寫操作,先寫入緩衝池,以一定的頻率(CheckPoint機制)刷新到磁盤。
  • 緩衝池的具體數據頁類型:數據頁、索引頁、undo頁、插入緩衝、自適應哈希索引等。
2.1.2 LRU List、Free List和Flush List

緩衝池通過改進的LRU算法管理數據頁。
Free List:數據庫剛啓動時,頁都在這個List中。

LRU List:用來管理已經讀取的頁,當數據庫剛啓動時,LRU列表是空的,當需要從緩衝池中新增頁時

  • 首先從Free List中查找是否有可用的空閒頁
  • 若有則將該頁從Free List中刪除,放到 LRU List中。
  • 否則根據LRU算法,淘汰LRU List末尾的頁,將該內存空間分配給新的頁。

Flush List:在LRU列表中的頁被修改後,稱該頁爲髒頁,即緩衝池中的頁和磁盤上的頁數據不一致。這時候數據庫會通過CHECKPOINT機制將髒頁刷新回磁盤,Flush List中就是髒頁列表。當然,LRU List中也有髒頁。

2.1.3 重做日誌緩存

InnoDB存儲引擎首先將重做日誌信息放到這個緩衝區,然後以一定頻率刷新到redo log文件。
刷新的時機:

  • Master Thread每秒刷新
  • 事務Commit時刷新
  • 重做日誌緩存剩餘空間小於1/2時刷新
2.1.4 額外的內存池

InnoDB存儲引擎中,對內存的管理是通過一種稱爲內存堆的方式進行的,在對一些數據結構本身的內存進行分配時,需要從額外的內存池中進行申請,當該區域的內存不夠時,會從緩衝池中進行申請。

2.3 CHECKPOINT 技術

爲了避免數據丟失,大多數數據庫採用了Write Ahead Log的策略,事物提交時,先寫redo log,再修改頁。
Checkpoint技術目的是爲了解決:

  • 縮短數據庫的恢復時間
  • 緩衝池不夠用時,將髒頁刷新到磁盤
  • 重做日誌不可用(因爲重做日誌是循環使用的)時,將髒頁刷新到磁盤

2.4 Master Thread 工作方式

內部由多個循環組成:

  • 主循環
    • 每秒一次的操作:
      • 刷新日誌緩衝到磁盤(總是)
      • 合併插入緩衝(可能)
      • 刷新髒頁(可能)
      • 切換到後臺循環(可能)
    • 每十秒一次的操作:
      • 刷新髒頁(總是)
      • 合併至多5個插入緩衝(總是)
      • 刷新日誌緩衝(總是)
      • 刪除無效Undo頁(總是)
  • 後臺循環
    • 刪除無用的Undo頁(總是)
    • 合併20個插入緩衝(總是)
    • 調回到主循環(總是)
    • 不斷刷新100個頁直到符合條件(可能)
  • 刷新循環
  • 暫停循環

2.5 InnoDB關鍵特性

2.5.1 插入緩衝

對於非聚集索引的插入或更新操作,不是每次都直接插入索引頁,而是先去判斷要插入到的非聚集索引頁是否在緩衝池中,若在,則直接插入,若不在,則先放到Insert Buffer對象中。然後再以一定頻率進行Insert Buffer和輔助索引頁子節點的merge操作。

  • 使用條件
    • 索引是輔助索引
    • 索引不是唯一的
  • 缺點
    • 如果發生宕機,可能有大量Insert Buffer未合併,恢復時間長。
    • 寫密集的情況,插入緩衝會佔用太多的緩衝池內存。
  • 內部實現
    • Insert Buffer內部是一顆B+樹,全局只有一顆,維護所有表的輔助索引。
    • 非頁節點存的是search key
    • 當一個輔助索引要插入到索引頁,首先看看緩衝池有沒有該頁,有則直接插入,沒有就構造一個search key 去查B+樹。
    • Insert Buffer Bitmap記錄索引頁的可用空間。
  • 合併時機
    • 輔助索引頁被讀取到緩衝池時
    • Insert Buffer Bitmap頁追蹤到該輔助索引頁已無可用空間時
    • Master Thread每10秒合併一次插入緩衝
2.5.2 兩次寫

在應用重做日誌前,用戶需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁,再進行重做,這就是double write。舉個例子來說,如果操作系統將頁寫入磁盤的時候發生了崩潰,該頁損壞,在恢復時,InnoDB存儲引擎可以從共享表空間中的doublewrite中找到副本,將其複製到表空間文件,再應用redo log文件。

  • doublewrite的構成:
    • 2MB的 doublewrite buffer(內存中)
    • 2MB的 共享表空間中的連續128頁(磁盤中)
  • doublewrite刷新髒頁的原理:
    將髒頁刷新到磁盤之前,會先寫入doublewrite buffer,然後通過該buffer分兩次寫,一次寫到共享表空間的物理磁盤,一次寫到數據文件的物理磁盤。
2.5.3 自適應哈索引

如果建立哈希索引可以帶來速度提升,則建立哈希索引,這就是自適應哈希索引。
他是通過緩衝池的B+樹頁構造而來的。

2.5.4 異步IO

用戶可以在發出一個IO請求後立即發出下一個,不需要等待上一個完成。
這就是AIO,所有IO請求發送完畢,等待所有IO操作完成。
AIO可以進行IO Merge操作,磁盤的寫入操作都是AIO完成的。

2.5.5 刷新鄰接頁

刷新髒頁同一個區的鄰接頁。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章