InnoDB硬核遊記[施工中]

緩衝池
* InnoDB基於磁盤存儲,其中的記錄按頁的方式來管理,爲了提升IO須要內存上開闢緩衝池
* 大小可經過innodb_buffer_pool_size確認
* 磁盤讀取頁時會先放在緩衝池,用於下一次的緩存命中
* 修改頁先修改緩衝池中的頁,再以必定的頻率將髒頁刷新到磁盤中(經過checkPoint機制確認頻率)
* 緩衝池中的支持的緩存類型有:
* 索引頁
* 數據頁(InnoDB中和索引頁是同一個東西)
* undo頁
* Insert Buffer
* 自適應哈希索引AHI
* lock info
* data dictionary
* 緩衝池不止一個
* 緩衝池的管理算法

* 經過變種(midpoint)的LRU來進行淘汰
    * 默認頁的大小16KB
    * 新讀取的頁被放入midpoint位置(5/8),midpoint後成爲old列表,前稱爲new列表
    * new儘可能長是爲了防止部分SQL操做訪問過多的頁使得熱點數據淘汰過快

checkPoint機制
* 用於刷新實例中的髒頁到硬盤的機制緩存

Insert Buffer
* 和數據頁一致,也是物理頁的一部分,用於提升二級索引(非惟一)的插入性能
* 就是把屢次插入放入buffer中,等到足夠的時機合併成一個索引頁再插入B+樹,減小離散性帶來的IO問題
* 因爲惟一索引須要查找索引頁來判斷惟一性,所以不能使用
* 數據結構上是一棵B+樹,全表只有一棵來負責這個Buffer,存放於共享表空間
* 頁由(space,[marker,]offset)惟一肯定(非葉節點),安全

* marker僅用於兼容性保證
    * space id用於確認表的位置
    * offset表示頁所在的偏移
* 葉子節點還多了metadata字段,內部包含有

    * IBUF_REC_OFFSET_COUNT,用於排序每一個記錄進入Insert Buffer的順序
    * IBUF_REC_OFFSET_TYPE
    * IBUF_REC_OFFSET_FLAGS
* 葉子節點第五列即是記錄實際插入的各個字段

Change Buffer
* 更普遍的支持Insert Delete Update緩衝(分別爲Insert Buffer / Delete Buffer / Purge Buffer)
* UPDATE操做的步驟:1.記錄標爲已刪除,2.真正將記錄刪除數據結構

double write機制
* 提供高於物理層面的高可用機制,在應用redo log前須要一個頁的副本,當寫入失效時,先經過副本還原頁,再進行redo,從而避免了頁損壞的問題異步

自適應哈希索引性能

* AHI根據緩存池B+樹上的熱點數據來創建哈希索引
    * 創建依據:按照同一索引的相同查詢方式訪問100次 且 訪問N >= 頁中記錄 / 16 次

AIO
* AIO可以讓IO請求連續發出,無需等待,提升IO能力
* InnoDB的AIO還會進行IO合併,內部會經過(space,offset)將可能合併的IO一併操做
* read ahead / 髒頁刷新 / 磁盤寫入均由AIO完成spa

雜亂筆記
* 插入聚簇索引是順序的,不須要磁盤的隨機讀取
* 插入非聚簇索引(且非惟一)時經過Insert Buffer提升IO性能
* MyISAM的緩衝池只緩存索引文件,不緩存數據文件
* 沒有主鍵會優先選取UNIQUE NOT NULL做爲主鍵,沒有再自行建立(多個則挑第一個定義的)線程

表的結構
* 全部數據存放於表空間
* 表空間由段(區(頁))組成
* 段有數據段和索引段之分(還有回滾段),但InnoDB是索引組織表形式,二者是等同的,索引即數據
* 區是連續的頁,一次申請4-5個區,每一個區有64個連續頁(1個區16KB
* 頁是InnoDB磁盤管理最小單位,可經過innodb_page_size設置4K/8K/16K
* 數據頁(B-TREE NODE)存放實際的行數據code

UNIQUE NOT NULL 和 PRIMARY區別
* 查詢避免不了從新往PRIMARY樹再查詢一遍(覆蓋索引除外)
* 相比事務依然可享受降級爲RECORD LOCK的待遇排序

全文索引
* InnoDB已經支持全文索引了
* 內部採用倒排索引機制,記錄(word,(columID,idx)...(多個))來快速查找(爲啥叫倒排,由於是根據value來找key)

關於幻讀
* 牛逼的InnoDB已經在repeatable read把幻讀解決了
* 具體是經過next-key lock機制
* 惟一性肯定時還經過鎖降級爲record lock來進一步加快速度
* 要想顯式關閉gap lock至少要將爲read commited

髒頁和髒數據
* 忽然感受沒差。。
* 髒頁是異步產生的,且保證最終一致性
* 髒數據是特指事務未提交的數據,一致性沒法保證


* 鎖分爲面向事務的lock和麪向線程的latch
* lock分爲行鎖、表鎖、意向鎖
* latch分爲mutex、rwlock
* 前者存在於Lock Manager的哈希表中,後者存在每一個數據結構中
* 前者經過圖判環、timeout機制檢測死鎖、後者無死鎖檢測,僅用於保證線程安全

行級鎖
* S Lock:容許事務讀取一行數據
* X Lock:容許事務刪除/更新一行數據
* 對於S鎖和X鎖,只有SS是兼容的,其餘組合不兼容(對於同一行而言)

意向鎖(透明)
* InnoDB中意向鎖就是表級鎖,意味請求事務獲取表中某幾行的鎖
* IS Lock:共享鎖
* IX Lock:排他鎖
* 意向鎖不阻塞除全表掃描外任何請求,我的感受就是個簡單標記

鎖的兼容性
* S鎖:對IS和S兼容
* X鎖:所有不兼容
* IS鎖:IS IX S兼容
* IX鎖:IS IX兼容(要寫入的行的安全性已經由X鎖保證,快速排除掉S鎖)

MVCC的使用時機?
* READ COMMITED / REPEATED READ使用一致性非鎖定讀(生成快照,無需等待X鎖。。。)
* READ COMMITED老是讀取鎖定行最新版本
* REPEATABLE READ老是讀取事務開始的版本

行鎖算法
* record lock:解決鎖定單個行
* gap lock:解決鎖定範圍行,阻止多個事務插入同一範圍
* next-key lock:前兩種機制mix,解決幻讀

* 具體的會鎖定(-inf,a_1] (a_1,a_2] (a_2,a_3] (a_3,inf),當事務在該範圍內再插入一個key,鎖會從新劃分該部分
    * 具備鎖降級機制,當切僅當使用具備惟一性的索引且操做單個行時,next-key降級爲record
    * 爲何不直接用gap lock解決幻讀?我以爲是沒問題的只是InnoDB實現上混合了record lock機制,在控制的粒度上更細膩(分段鎖總比全局鎖好)

Question * 緩衝池 - OK * 索引到底存儲在哪 - OK * 我的認爲數據頁和索引頁都在磁盤,可是緩衝池機制會把訪問到的臨時放在內存上經過LRU管理,可是索引的根會常駐內存以快速找到磁盤索引的入口 * 索引和普通字段的存儲區別 - OK *

相關文章
相關標籤/搜索