一、存儲引擎 1、InnoDB引擎 設計目標是面向線上事務(OLTP)處理的應用。 支持事務、行級鎖、通過多版本併發控制(MVCC)支持高併發、提供一致性非鎖定讀、next-key locking避免幻讀、主鍵聚集索引 2、MyISAM引擎 設計目標是面向OLAP應用。 不支持事務、不支持行鎖、表鎖 ...
一、存儲引擎
1、InnoDB引擎
設計目標是面向線上事務(OLTP)處理的應用。
支持事務、行級鎖、通過多版本併發控制(MVCC)支持高併發、提供一致性非鎖定讀、next-key locking避免幻讀、主鍵聚集索引
2、MyISAM引擎
設計目標是面向OLAP應用。
不支持事務、不支持行鎖、表鎖設計、支持全文索引
3、其他存儲引擎
略
二、InnoDB體繫結構
1、線程模型
InnoDB存儲引擎是多線程模型,後臺有多個不同的線程,用於處理不同的任務。
- Master Thread:核心線程,將緩衝池中的數據非同步刷新到磁碟
- IO Thread:負責io請求的回調處理
- Purge Thread:負責undo頁的回收
- Page Cleaner Thread:負責臟頁的刷新
1.1、Master Thread
內部由多個迴圈組成。包括主迴圈(loop),後臺迴圈(background loop)
主迴圈每隔一秒的操作
- 把日誌緩衝刷新到磁碟,即使這個事務還沒有提交。很好的解釋了再大的事務提交時間也很短
- 合併插入緩衝
- 至多刷新n(可配置,自動調整,1.2版本之後)個臟頁到磁碟
- 沒有用戶活動,切換到background loop
主迴圈每隔10秒的操作
- 合併最多5個插入緩衝
- 緩衝日誌刷新到磁碟
- 刪除無用的undo頁
- 刷新臟頁到磁碟(超過70%,刷新100頁,沒超過70%,刷新10頁)
2、記憶體模型
2.1、緩衝池
InnoDB是基於磁碟的存儲系統,為了彌補cpu和磁碟性能的差距,將從磁碟讀出的數據保存在記憶體中,下次讀取先從緩衝池中讀取。有數據更新也先更新緩衝池的數據,通過checkpoint機制寫回磁碟。緩衝池中包括索引頁、數據頁、undo頁、插入緩存、鎖信息等
2.2、緩衝池管理(LRU List)
最近做少使用演算法,最頻繁使用的頁在List前端,最少使用的頁在List末尾。當緩衝池容量不足容納新數據時,先從尾部釋放數據頁。新數據插入在List的midpoint(List的5/8,對朴素LRU的優化,朴素LRU插入List頭部。避免大量一次性查詢把頻繁使用的頁刷出緩衝池)
2.3、臟頁管理(Flush List)
當數據被更新,緩衝池中的數據首先被更新,修改之後的頁稱為臟頁。臟頁會保存到Flush List中,通過checkpoint機制把臟頁數據寫回磁碟
2.4、重做日誌(redo log)緩衝
首先把重做日誌信息存入緩衝區,然後按照一定頻率同步到重做日誌文件中。以下三種情況都會觸發重做日誌緩存同步到重做日誌文件:
- Master Thread 每隔一秒刷新
- 每個事務提交時
- 重做日誌緩衝池容量達到閾值,一般是1/2
2.5、check point技術
為了防止宕機導致事務未提交信息丟失,在事務提交時,先把數據保存到重做日誌(redo log)中,再修改頁。保證了持久性(D)
發生宕機,重啟之後自動從重做日誌中恢複數據。
但是這裡有以下問題:
- 重做日誌過大,宕機重啟恢複數據太慢
- 重做日誌不能無限擴容,需要迴圈利用
- 重做日誌不可用怎麼辦
check point就是為瞭解決這些問題:
- 縮短資料庫恢復時間
- 重做日誌不可用,刷新臟頁
- 緩衝池不夠用,將臟頁刷新到磁碟
check point觸發時機:
- Master Thread check point。每隔一秒觸發一次
- LRU List check point。保證LRU List中有100個空閑頁,如果清理的頁中有臟頁,觸發check point 強制刷新臟頁數據到磁碟
- Dirty Page too mush check point。臟頁太多,超過閾值,觸發check point 強制刷新臟頁數據到磁碟
3、關鍵特性
3.1、插入緩存
(1)為什麼需要插入緩存?
我們知道索引分為聚集索引和非聚集索引。
聚集索引一般是自增的唯一id,頁中的數據記錄按順序存放,寫入的時候不需要隨機讀取其他頁中的數據,寫入速度很快(如果用UUID作為主鍵,寫入速度會很慢,每次寫入都需要隨機讀)
實際應用中,一張表往往還有非聚集索引的存在。非聚集索引葉子節點的插入不是順序的,需要離散的訪問非聚集索引頁,隨機讀取導致了插入數據的性能下降。插入緩存就是為了優化這種場景下的插入速度
(2)什麼場景會觸發插入緩存?
- 索引是輔助索引
- 索引不是唯一索引
對於非聚集索引的插入,會先判斷非聚集索引頁是否在緩衝池中,如果在緩衝池中,直接插入索引頁,如果沒在,先放入到insert buffer對象中,然後再以一定的頻率把insert buffer中的數據和非聚集索引的葉子節點進行數據合併
(3)實現原理
insert buffer 的數據結構也是B+樹,有記錄要插入的時候,會對記錄進行封裝,按照記錄的插入順序進行編號,是順序寫入
3.2、兩次寫
(1)為什麼需要插入兩次寫?
如果InnoDB正在寫入某個頁的數據到磁碟,正好寫了一部分的時候宕機了。這種情況稱為部分寫失效,會導致數據丟失
(2)實現原理
double write由兩部分組成。一部分是double write緩衝,一部分是物理磁碟連續共用空間。在刷新臟頁數據的時候,先複製一份臟頁數據到兩次寫緩存中,在順序寫入共用磁碟中(因為是順序寫性能影響不大)。最後寫入數據存儲磁碟中(離散寫)
3.3、自適應hash索引優化
hash是非常快的查詢方式,時間負責度為O(1)。而B+樹的查找次數取決於樹的高度。
如果一個頁被頻繁的訪問,而且訪問模式也相同(聯合索引使用最左原則)。會自動針對這頁數據根據緩衝池中的索引建立Hash索引提高查詢速度
3.4、非同步IO
可以在發出一個IO請求後,在發出另外的IO請求,沒必要等待上一次的IO請求處理完成。把全部IO請求都發出,等待所有IO操作的完成,這就是AIO(Aysnc IO)