Innodb存儲引擎

看了姜老師的技術內幕,做了如下筆記


Innodb線程:

innodb是多線程模型,有多個後臺線程負責處理不同任務

1、主線程

負責將緩衝池中的數據異步刷新到磁盤,髒頁刷新,合併插入緩衝,undo頁回收等


2、IO線程

innodb存儲引擎中使用了大量AIO(異步io)來處理IO請求,IO線程主要負責這些IO請求的回調。


3、purge線程

事務提交後,其所使用的undolog可能不再需要,因此需要purge thread來回收。


4、page cleaner 線程

負責刷新髒頁


Innodb的內存:

1、緩衝池(innodb_buffer_pool)

    Innodb存儲引擎是基於磁盤存儲的,並將其中的記錄按照頁的方式進行管理。由於CPU與磁盤速度之間的鴻溝,基於磁盤的數據庫系統,通常使用緩衝池技術提高數據庫的整體性能。

    緩衝池可以理解爲一塊內存區域,在數據庫中讀取頁的操作,首先將磁盤中讀到的頁放在緩衝池中,下次再讀相同的頁時,判斷是否在緩衝池中,在就直接讀取,即命中。不在就到磁盤中去讀取。

    對於數據庫中頁的修改,首先修改緩衝池中的頁,然後再以一定頻率刷回磁盤。注意:頁從緩衝池刷回磁盤並不是每次頁變更了都會觸發,而是通過檢查點機制刷新回磁盤。

    緩衝池中緩存的數據頁類型有:索引頁,數據頁,undo頁,插入緩衝,自適應哈希,innodb鎖信息,數據字典信息等。

2、LRU list、Free list、Flush list

    LRU列表

    數據庫中的緩衝池是通過LRU(最近最少使用)算法來進行管理的,innodb對LRU算法進行了一些優化,在LRU列表中加入了midpoint位置,默認情況下,該位置位於LRU列表長度的5/8處。

    在midpoint之前的列表稱爲new,之後的稱爲old,可以簡單理解爲new列表中的頁都是活躍的熱點頁。

    mid位置頁升爲熱點數據需要等待參數innodb_old_blocks_time,已保證儘量不將LRU列表的將熱點數據刷出。


    Free列表

    數據庫剛啓動時,LRU列表爲空,所有頁都存在Free列表中,要從緩衝池分頁時,先從Free列表查看有沒有空閒頁,有,將該頁從Free列表刪除,放到LRU列表中。沒有,根據LRU算法,淘汰LRU列表末尾的頁,將內存空間分配給新的頁。

    LRU list包含unzip_LRU list,LRU list頁大小爲16K,unzip_LRU list的頁大小可能爲1k、2k、4k、8k。

    unzip_LRU列表對不同壓縮頁大小的頁進行分別管理,其次通過夥伴算法進行內存的分配。

    例如需要從緩衝池申請一個4k的頁,檢查4k的unzip_LRU列表是否有空閒頁,有,直接使用,沒有,查找8k的unzip_LRU列表,若有空閒頁,將其分爲2個4K的頁,存到4k的unzip_LRU列表,若沒有空閒頁,則將LRU列表一個16k的頁,拆成一個8k和2個4k的頁,存入對應的unzip_LRU列表。


    Flush列表

    LRU列表中的頁被修改後,稱爲髒頁,即緩衝池中的頁和磁盤上的頁不一致。這時,數據庫會通過checkpoint機制將髒頁刷回磁盤。

    Flush列表中的頁即爲髒頁,髒頁既存在於LRU列表,也存在於Flush列表。

    LRU列表用來管理緩衝池中頁的可用性,Flush列表用來管理將頁刷新回磁盤,兩者互不影響。


3、重做日誌緩衝(redo log buffer)

    innodb存儲引擎先將重做日誌信息放入這個緩衝區,再按照一定頻率將其刷新到重做日誌文件,用戶只需要保證每秒的事務不超過這個緩衝大小即可。默認8M

    在下面三種情況下,會將重做日誌緩衝中的內容刷新到重做日誌:

    1)、主線程,每一秒將重做日誌緩衝刷新到重做日誌文件。

    2)、每個事務提交時,會將重做日誌緩衝刷新到重做日誌文件。

    3)、當重做日誌緩衝大小小於1/2時,會將重做日誌緩衝刷新到重做日誌文件。


checkpoint技術

檢查點技術主要解決以下幾個問題:

1)、縮短數據庫恢復時間

    當數據庫宕機時,數據庫不需要重做所有的日誌,checkpoint之前的已經刷回磁盤,只需要重做checkpoint之後的日誌,大大減少了恢復時間。

2)、緩衝池不夠時,將髒頁刷新到磁盤

    當緩衝池不夠用時,會溢出最近最少使用的頁,如果這個頁是髒頁,那麼強制checkpoint,將髒頁刷新回磁盤。

3)、重做日誌不可用時,刷新髒頁


在innodb中checkpoint分爲兩種:

Sharp checkpoint:在數據庫關閉時,將所有髒頁刷新回磁盤,默認的。

Fuzzy checkpoint:只刷新一部分髒頁到磁盤。


可能發生Fuzzy checkpoint的幾種情況:

1)、master thread checkpoint

    差不多每10秒,從髒頁列表刷新一部分髒頁到磁盤。

2)、flush_LRU_list checkpoint

    innodb需要保證LRU列表有innodb_lru_scan_depth個空閒頁可以使用,如果沒有,就會從lru列表末尾移除,如果移除的有髒頁,就進行checkpoint。

3)、異步/同步 Flush checkpoint

4)、dirty page too much checkpoint

    當緩衝池中髒頁數量大於innodb_max_dirty_pages_pct,強制checkpoint。


Master thread

    master thread具有最高的線程優先級,由多個循環組成:主循環loop、後臺循環backgroup loop、刷新循環flush loop、暫停循環suspend loop。master thread會根據數據庫運行狀態,在這些循環中切換。

    loop循環,分爲每1秒操作和每10秒操作:

    每1秒:

    1)、日誌刷新緩衝刷新到磁盤,即使這個事務沒有提交(總是)

    2)、合併插入緩衝(可能)(innodb判斷前1秒發生的IO次數是否小於innodb_io_capacity的5%次,則合併緩衝innodb_io_capacity的5%)

    3)、至多刷新innodb_io_capacity個緩衝池中的髒頁到磁盤(可能)(判斷當前緩衝池中髒頁的比例是否超過了innodb_max_dirty_pages_pct)

    4)、當前沒有用戶活動,則切換到backgroup loop(可能)

    

    每10秒:

    1)、刷新innodb_io_capacity個髒頁到磁盤(可能)(innodb判斷過去10s內io是否小於innodb_io_capacity次)

    2)、合併innodb_io_capacity的5%個插入緩衝(總是)

    3)、將日誌緩衝刷到磁盤(總是)

    4)、刪除無用的undo頁(總是)

    5)、刷新innodb_io_capacity個或innodb_io_capacity的10%個髒頁到磁盤(總是)(判斷緩衝池中的髒頁比例,如果大於70%刷新innodb_io_capacity個,小於70%刷新innodb_io_capacity的10%個)


   backgroup loop:

    1)、刪除無用的undo頁(總是)

    2)、合併innodb_io_capacity個插入緩衝(總是)

    3)、跳回到主循環(總是)

    4)、不斷刷新innodb_io_capacity個頁直到符合條件(可能跳到flush loop中完成)


Innodb關鍵特性

    1)、插入緩衝

        並不是所有的主鍵插入都是順序的,例如UUID這樣的主鍵值或者主鍵爲自增,但插入爲指定值而不是null值,同樣可能會出現非連續插入的現象。

        對於非聚集索引的插入或更新操作,並不是每次都直接插入到索引頁。先判斷插入的非聚集索引頁是否在緩衝池中,在,直接插入,不在,先放到insert buffer中。然後再以一定頻率進行Insert buffer和索引頁子節點的合併操作。

        insert buffer使用要滿足兩個條件:

        a、索引是輔助索引

        b、索引不唯一

    2)、兩次寫

        刷新髒頁時,先將髒頁刷到double write buffer中(2M),再從double write buffer中分兩次(1次1M)順序寫入磁盤上共享表空間的連續128個頁(2M),然後再從double write buffer離散的寫入磁盤,如果寫入失敗了再去共享表空間裏拿副本來恢復。

    3)、自適應哈希

        AHI是通過緩衝池B+樹頁來夠造的。innodb會根據訪問頻率和模式,自動爲熱點頁添加hash索引。

        添加hash索引的條件:

        a、連續以同一模式訪問100次

        b、頁以同一模式訪問N次,N=頁中記錄*1/16

    4)、異步IO

        用戶可以發出一個io請求後,跟着再發出一個io請求,當全部IO請求發送完畢後,等待所有IO操作完成,這就是AIO。即不用等一個IO完成才能再發出一個IO。

        AIO會判斷多個頁是否是連續的,如果是,會進行merge操作,合併爲一個IO,這就提升了IOPS。

    5)、刷新鄰接頁

        當刷新一個髒頁時,innodb會檢查該頁所在的區的所有頁,如果是髒頁,那麼就一起刷新。固態硬盤可以考慮關閉,機械硬盤建議開啓。參數爲<innodb_flush_neighbors>0關閉、1開啓。


    

    

    




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