Innodb 存儲引擎(轉)

第一部分:線程html

Innodb是一個多線程的,各個線程負責不一樣的任務。主要的線程有:Master Thread、IO Thread、Purge Thread、Page Cleaner Threadmysql

一,Master Thread :刷寫數據、回收undo、回收髒頁、合併插入緩衝
算法

      具備最高的優先級別,內部有多個循環(loop)組成:主循環(loop)、後臺循環(background loop)、刷新循環(flush loop)、暫停循環(suspend loop),根據數據庫的運行狀況會在這些循環中切換。sql

      該線程主要負責刷寫數據,包括緩衝池的數據異步刷寫到磁盤,髒頁的刷寫、合併插入緩衝、UNDO頁的回收等。在主循環(loop)中有2大部分的操做:每1秒和每10秒的操做。數據庫

build-in Innodb緩存

每一秒的操做:安全

1)日誌緩衝刷寫到磁盤,即便這個事務尚未提交(老是)。這解釋了再大的事務提交的時間也很短。數據結構

2)合併最多5個插入緩衝(可能)。先判斷前1秒的IO次數是否小於5次,小於則進行合併插入緩衝的操做。多線程

3)刷寫100個髒頁到磁盤(可能)。先判斷緩衝池的比例是否超過了innodb_max_dirty_pages_pct的值,若是超過則刷寫100個髒頁到磁盤。併發

4)若是沒有用戶活動則切換後臺循環線程。

每十秒的操做:

1)刷寫100個髒頁到磁盤(可能)。先判斷前10秒的IO次數是否小於200,小於則刷寫100個髒頁到磁盤。

2)合併最多5個插入緩衝(老是)。

3)日誌緩衝刷寫到磁盤(老是)。

4)刪除最多20個無用的UNDO頁(老是)。

5)刷寫100或10個髒頁到磁盤(老是)。先判斷緩衝池的髒頁比例是否大於70%,大於則刷寫100個髒頁到磁盤,小於則刷寫10個髒頁到磁盤。

經過每一秒和每十秒的信息看出:Master Thread對IO的操做都有限制,影響到了存儲引擎的性能,爲了提升性能,在Plugin innodb上作了提高:

Plugin Innodb

      參數:innodb_io_capacity 表示磁盤IO的吞吐量,控制Innodb checkpoint時的IO能力,默認是200。對於刷新到磁盤的數量,會按照該參數的百分比進行刷寫,而不是固定100、10等限制的大小刷寫。

如以前的:合併5個插入緩衝 變成 合併5%*innodb_io_capacity的插入緩衝;

               刷寫100個髒頁   變成 合併 100%*innodb_io_capacity的髒頁;

               刷寫10個髒頁    變成 合併 10%*innodb_io_capacity的髒頁;

innodb_io_capacity設置爲500,

則刷寫100個髒頁大小爲:100*16/1024 = 1.5625M;按照innodb_io_capacity的大小設置則髒頁大小爲:500*16/1024 = 7.8125M。

接着看後臺循環(background loop):沒有用戶活動,數據庫空閒或則關閉時,就會切換到這個循環,該循環下作以下事情:

1)刪除無用的UNDO頁(老是)。

2)合併20個插入緩存(老是)。

3)跳回主循環。若是不空閒了則跳回主循環,不然跳到flush loop。

接着看刷新循環(flush loop):

1)不斷刷寫100個髒頁到磁盤。先判斷緩衝池裏髒頁比例是否大於innodb_max_dirty_pages_pct,大於則不斷刷新只到小於爲止。

flush loop 沒有事可作,則切換到暫停循環(suspend loop),將Master Thread掛起,等待事件發生。若用戶開啓innodb 存儲引擎,可是沒用innodb表,則Master Thread老是掛起。

二,IO Thread :能夠用參數innodb_read_io_threads和innodb_write_io_threads 來控制read和write。

      Innodb存儲引擎大量使用了AIO(異步IO),提升了磁盤的操做性能。IO Thread 主要負責這些異步IO的回調。built-innodb有4個IO Thread:write、read、insert buffer、log。

三:Purge Thread:回收UNDO。5.5以後的參數,從Master Thread獨立出來

      回收無用的UNDO頁,在MySQL 5.5以前是在Master Thread中完成的。5.5以後,獨立到了單獨的線程中完成,減輕了Master Thread線程的工做。提高CPU的使用率和存儲引擎的性能。

經過參數innodb_purge_threads 來開啓,在5.5中只能也只有1能夠設置。5.6能夠設置大於1。另外一個參數:innodb_purge_batch_size 來控制每次回收UNDO頁的數量,在5.5以前默認是20(寫死),5.5以後能夠根據狀況調整該參數。

四:Page Clean Thread:刷寫髒頁,5.6以後的參數,從Master Thread獨立出來

      5.6裏開始支持,髒頁的刷寫線程。從Master Thread裏面獨立出來。減輕了Master Thread 的工做,和對用戶查詢的阻塞。進一步提升Innodb 存儲引擎的性能和併發。

 

第二部分:內存

      Innodb的內存數據對象包括:緩衝池即innodb_buffer_pool(數據頁、索引頁、插入緩衝、自適應哈希索引、鎖信息、數據字典)、重作日誌緩衝即redo log buffer(innodb_log_buffer_size)、額外內存池(innodb_additional_mem_pool_size)。5.5開始有多個緩衝池實例(innodb_buffer_pool_instances),根據哈希值進行分配,好處是減小了數據庫內部的資源競爭,提升併發處理能力。只有配置BP大於1G的時候,多實例BP才能生效。默認爲1。

一:緩衝池即innodb_buffer_pool     

      Innodb Buffer Pool是緩存數據和索引的緩衝區,負責管理free list(初始化空閒頁等),flush list(緩衝池產生的髒頁),LRU list(經過LRU算法管理頁面交換的,LRU List分爲2塊:LRU_new、LRU_old。LRU_old爲鏈表長度的3/8。頁讀取先進入old,訪問時候從old進入到new。)即數據庫的緩衝池(BP)能夠當作一個LRU列表,根據最近最少使用算法進行管理,最頻繁使用的在頂端,最少使用的在末端。當不能存放讀取到的新頁時,最早釋放末端的頁,將新頁存放到頂端。Innodb在該LRU算法上進行了改進,加了一個midpoint的位置,新讀取到的頁不是放到頂端,而是放到midpoint的位置。由於某些SQL會使老的LRU算法出現問題:全索引、全表、mysqldump等相似的掃描多個頁甚至是所有頁的一次性SQL,會讓緩衝池中真正的熱點數據被刷出,影響緩衝池的效率。

      midpoint位置在LRU列表的5/8處,由參數innodb_old_blocks_pct控制。midpoint 以前的位置稱爲new(young)即活躍的熱點數據,以後的位置稱爲old。該參數默認值爲37(尾端開始的3/8處),要是熱點數據不少,則能夠設置該參數,如20(尾端開始的1/5處)。

      另外一個參數Innodb_old_blocks_time :等到該時間後,再讀取該頁則會進入到new端,有效的避免了對於上述SQL對BP的污染。默認是0,單位是毫秒。如設置爲1000則表示:讀到該頁到midpoint的位置,要再等1秒以後讀取該頁才能進入new列表。而0則表示讀取到該頁則會直接被放入到new列表。

      page made young:頁從LRU的old列表加入到new列表。

      page not made young:因爲Innodb_old_blocks_time的設置(非0),致使頁沒有從LRU的old列表加入到new列表。

上面能夠經過 show engine innodb status 查看到。

二:重作日誌緩衝即Innodb_log_buffer_size(事務日誌緩存)

      Innodb存儲引擎首先將重作(事務)日誌信息放入到這個緩衝區,再按照必定頻率(innodb_flush_log_at_trx_commit)刷寫到重作(事務)日誌文件中。日誌緩衝大小設置爲每秒產生的事務量便可。由於上面提過了Master Thread線程會每秒刷寫日誌緩衝到日誌文件。還有其餘的狀況也會刷寫:如每次事務提交和重作日誌緩衝空間小於1/2的時候,當redo log buffer不夠大的時候,會產生等待。能夠經過show global status like 'Innodb_log_waits' 查看redo log buffer的等待狀態。

三:額外的內存池(innodb_additional_mem_pool_size)

      對數據結構自己的內存分配,還有鎖、等待以及LRU等信息。

      

第三部分:Checkpoint

      事務提交時,先寫重作日誌,再修改頁。知足日誌先行的原則。這樣即便刷寫數據到磁盤發生宕機也能夠經過redo log 進行恢復,符合ACID中的D:持久性。事務日誌(redo log)還能夠提升事務的提交(順序IO)和崩潰時候的恢復。

Checkpoint技術的目的:

①縮短數據庫的恢復時間。數據庫宕機,不須要作全部的redo log,Checkpoint以前的頁都已經刷寫到磁盤,只須要對其以後的redo log 進行恢復。

②緩衝池(BP)不夠,刷寫髒頁。當緩衝池不夠,則根據LRU算法會溢出最近最少使用的頁,若該頁是髒頁則須要強制執行Checkpoint進行刷寫。

③重作日誌(redo log)不可用,則刷寫髒頁。由於redo log 是循環使用的,當新的事務須要寫到日誌文件時,而日誌文件裏的事務尚未來得及應用,不能被新事務覆蓋使用時,須要強制執行Checkpoint進行刷寫,將緩衝池中的頁刷寫到重作日誌的位置。

Checkpoint作的事情就是把緩衝池中的髒頁刷寫到磁盤。觸發刷寫的操做的時機有:

數據庫關閉,innodb_fast_shutdown(Innodb外部)

Master Thread每秒/每10秒刷寫(Innodb內部)

③Flush_LRU_LIST,LRU列表須要有100個頁空閒給用戶查詢使用,若沒有則會阻塞查詢操做,會把LRU列表的末端移除,若爲髒頁則須要Checkpoint。

④redo log不可用,須要進行強制的刷寫操做。未刷寫的頁:lsn - checkpoint 。如redo log爲2G。

* 未刷寫的頁<75%*2G,不須要刷寫

* 75%*2G<未刷寫的頁<90%*2G,須要刷寫,直到知足未刷寫的頁<75%*2G

在5.6以前,③和④過程會阻塞用戶查詢,並等待髒頁刷寫完成爲止。5.6後有專門的Page Cleaner Thread,不會阻塞。

⑤緩衝池中的髒頁太多,超過了innodb_max_dirty_pages_pct的值,會進行刷寫。

 

第四部分:Innodb關鍵特性

      Innodb存儲引擎的關鍵特性包括:插入緩存(Insert Buffer -> Change Buffer)、兩次寫(Double Write)、自適應哈希索引(Adaptive Hash Index)、異步IO(Async IO)、刷寫鄰居頁(Flush Neighbor Page)

一,插入緩衝(Insert Buffer/Change Buffer):提高插入性能

      InnoDB爲了避免更新數據時更新索引損失太多性能,使用了這種稱爲Insert Buffer的方法來緩衝索引更新。

      只對於非彙集索引(非惟一)的插入和更新有效,對於每一次的插入不是寫到索引頁中,而是先判斷插入的非彙集索引頁是否在緩衝池中,若是在則直接插入;若不在,則先放到Insert Buffer 中,再按照必定的頻率進行合併操做。這樣一般能將多個插入合併到一個操做中,提高插入性能
按照Master Thread的調度規則來合併不是惟一索引和索引頁中的葉子結點,這樣常常能減小更新索引的代價。使用插入緩衝的條件:

* 非彙集索引

* 非惟一

插入緩衝最大使用空間爲1/2的緩衝池大小,不能調整大小,在plugin innodb中,升級成了Change Buffer。不只對insert,對update、delete都有效。其參數是:

innodb_change_buffering,設置的值有:inserts、deletes、purges、changes(inserts和deletes)、all(默認)、none。

能夠經過參數控制其使用的大小:

innodb_change_buffer_max_size,默認是25,即緩衝池的1/4。最大可設置爲50。在5.6中被引入。

上面提過在必定頻率下進行合併,那所謂的頻率是什麼條件?

1)輔助索引頁被讀取到緩衝池中。正常的select先檢查Insert Buffer是否有該非彙集索引頁存在,如有則合併插入。

2)輔助索引頁沒有可用空間。空間小於1/32頁的大小,則會強制合併操做。

3)Master Thread 每秒和每10秒的合併操做。

二,兩次寫(DoubleWrite)

      提升數據安全,當頁寫入失效時,先經過頁的副本(共享表空間中)來還原,再經過redo log 來重作。由2部分組成,一部分是內存中double write buffer,2M大小;另外一部分是磁盤上共享表空間的連續的128頁,即2個區(extent),2M大小的doublewrite。

      緩衝池刷寫髒頁時,並非直接寫磁盤,而是先寫到內存中的DoubleWrite中,以後再經過DoubleWrite順序的寫到共享表空間的DoubleWrite中,最後刷寫磁盤。這樣意味這刷寫數據都要多寫一份,增長了IO。但DoubleWrite是順序的,因此開銷不大。相比之下,犧牲一點點開銷來提高安全是頗有必要的。
參數:

Innodb_dblwr_pages_written:寫的頁數

Innodb_dblwr_writes:寫的次數

Innodb_dblwr_pages_written:Innodb_dblwr_writes 要是小於64:1則寫壓力不高。大於則表示壓力高

Innodb_dblwr_pages_written和Innodb_buffer_pool_flushed (從緩衝池刷寫到磁盤的頁的數量)應該是一致的,由於緩衝池的刷寫都會先存放到doublewirte中,便可以經過他們看出數據庫的寫入量。

參數skip_innodb_doublewrite 禁止雙寫。雙寫緩存的更多信息能夠看關於innodb中兩次寫的探索

三,自適應哈希索引:提升查詢效率

四,異步IO:提升磁盤的操做性能

      5.5以前,是經過代碼實現的(不能修改),5.5以後新增了參數:innodb_use_native_aio來控制是否啓用,默認值得爲ON。啓用恢復數據提高75%。

五,刷新鄰接頁

      工做原理:刷寫一個髒頁時,會檢測該頁所在的區(extent:64頁,1M)的其餘頁是否也有髒頁,有則一塊兒刷寫。5.6能夠經過參數來控制是否刷寫:

innodb_flush_neighbors,機械磁盤建議開啓,固態硬盤建議設置爲0,即關閉。

相關文章
相關標籤/搜索