您好,登錄后才能下訂單哦!
概要:
我們知道InnoDB采用Write Ahead Log策略來防止宕機(jī)數(shù)據(jù)丟失,即事務(wù)提交時(shí),先寫重做日志,再修改內(nèi)存數(shù)據(jù)頁,這樣就產(chǎn)生了臟頁。既然有重做日志保證數(shù)據(jù)持久性,查詢時(shí)也可以直接從緩沖池頁中取數(shù)據(jù),那為什么還要刷新臟頁到磁盤呢?如果重做日志可以無限增大,同時(shí)緩沖池足夠大,能夠緩存所有數(shù)據(jù),那么是不需要將緩沖池中的臟頁刷新到磁盤。但是,通常會(huì)有以下幾個(gè)問題:
重做日志被設(shè)計(jì)成可循環(huán)使用,當(dāng)日志文件寫滿時(shí),重做日志中對應(yīng)數(shù)據(jù)已經(jīng)被刷新到磁盤的那部分不再需要的日志可以被覆蓋重用。
InnoDB引擎通過LSN(Log Sequence Number)來標(biāo)記版本,LSN是日志空間中每條日志的結(jié)束點(diǎn),用字節(jié)偏移量來表示。每個(gè)page有LSN,redo log也有LSN,Checkpoint也有LSN??梢酝ㄟ^命令show
engine innodb status來觀察:
Flush LRU List Checkpoint
InnoDB要保證LRU列表中有100左右空閑頁可使用。在InnoDB1.1.X版本前,要檢查LRU中是否有足夠的頁用于用戶查詢操作線程,如果沒有,會(huì)將LRU列表尾端的頁淘汰,如果被淘汰的頁中有臟頁,會(huì)強(qiáng)制執(zhí)行Checkpoint刷回臟頁數(shù)據(jù)到磁盤,顯然這會(huì)阻塞用戶查詢線程。從InnoDB1.2.X版本開始,這個(gè)檢查放到單獨(dú)的Page
Cleaner Thread中進(jìn)行,并且用戶可以通過innodb_lru_scan_depth控制LRU列表中可用頁的數(shù)量,默認(rèn)值為1024。
Async/Sync Flush Checkpoint
是指重做日志文件不可用時(shí),需要強(qiáng)制將臟頁列表中的一些頁刷新回磁盤。這可以保證重做日志文件可循環(huán)使用。在InnoDB1.2.X版本之前,Async
Flush Checkpoint會(huì)阻塞發(fā)現(xiàn)問題的用戶查詢線程,Sync Flush
Checkpoint會(huì)阻塞所有查詢線程。InnoDB1.2.X之后放到單獨(dú)的Page Cleaner Thread。
Dirty Page Too Much Checkpoint
臟頁數(shù)量太多時(shí),InnoDB引擎會(huì)強(qiáng)制進(jìn)行Checkpoint。目的還是為了保證緩沖池中有足夠可用的空閑頁。其可以通過參數(shù)innodb_max_dirty_pages_pct來設(shè)置,默認(rèn)為75%。
Innodb的事務(wù)日志是指Redo log,簡稱Log,保存在日志文件ib_logfile*里面。Innodb還有另外一個(gè)日志Undo log,但Undo log是存放在共享表空間里面的(ibdata*文件)。
由于Log和Checkpoint緊密相關(guān),因此將這兩部分合在一起分析。
名詞解釋:LSN,日志序列號,Innodb的日志序列號是一個(gè)64位的整型。
Log寫入LSN實(shí)際上對應(yīng)日志文件的偏移量,新的LSN=舊的LSN + 寫入的日志大小。舉例如下:
LSN=1G,日志文件大小總共為600M,本次寫入512字節(jié),則實(shí)際寫入操作為:
| --- 求出偏移量:由于LSN數(shù)值遠(yuǎn)大于日志文件大小,因此通過取余方式,得到偏移量為400M;
| --- 寫入日志:找到偏移400M的位置,寫入512字節(jié)日志內(nèi)容,下一個(gè)事務(wù)的LSN就是1000000512;
Checkpoint寫入
Innodb實(shí)現(xiàn)了Fuzzy Checkpoint的機(jī)制,每次取到最老的臟頁,然后確保此臟頁對應(yīng)的LSN之前的LSN都已經(jīng)寫入日志文件,再將此臟頁的LSN作為Checkpoint點(diǎn)記錄到日志文件,意思就是“此LSN之前的LSN對應(yīng)的日志和數(shù)據(jù)都已經(jīng)寫入磁盤文件”?;謴?fù)數(shù)據(jù)文件的時(shí)候,Innodb掃描日志文件,當(dāng)發(fā)現(xiàn)LSN小于Checkpoint對應(yīng)的LSN,就認(rèn)為恢復(fù)已經(jīng)完成。
Checkpoint寫入的位置在日志文件開頭固定的偏移量處,即每次寫Checkpoint都覆蓋之前的Checkpoint信息。
由于Checkpoint和日志緊密相關(guān),將日志和Checkpoint一起說明,詳細(xì)的實(shí)現(xiàn)機(jī)制如下:
如上圖所示,Innodb的一條事務(wù)日志共經(jīng)歷4個(gè)階段:
1) 創(chuàng)建階段:事務(wù)創(chuàng)建一條日志;
2) 日志刷盤:日志寫入到磁盤上的日志文件;
3) 數(shù)據(jù)刷盤:日志對應(yīng)的臟頁數(shù)據(jù)寫入到磁盤上的數(shù)據(jù)文件;
4) 寫CKP:日志被當(dāng)作Checkpoint寫入日志文件;
對應(yīng)這4個(gè)階段,系統(tǒng)記錄了4個(gè)日志相關(guān)的信息,用于其它各種處理使用:
Log sequence number(LSN1):當(dāng)前系統(tǒng)LSN最大值,新的事務(wù)日志LSN將在此基礎(chǔ)上生成(LSN1+新日志的大?。?;
Log flushed up to(LSN2):當(dāng)前已經(jīng)寫入日志文件的LSN;
Pages flushed up to(LSN3):當(dāng)前最舊的臟頁數(shù)據(jù)對應(yīng)的LSN,寫Checkpoint的時(shí)候直接將此LSN寫入到日志文件;
Last checkpoint at(LSN4):當(dāng)前已經(jīng)寫入Checkpoint的LSN;
對于系統(tǒng)來說,以上4個(gè)LSN是遞減的,即: LSN1>=LSN2>=LSN3>=LSN4.
具體的樣例如下(使用show engine innodb status \G命令查看)
當(dāng)事務(wù)執(zhí)行速度大于臟頁刷盤速度時(shí),Ckp age和Buf age會(huì)逐步增長,當(dāng)達(dá)到async點(diǎn)的時(shí)候,強(qiáng)制進(jìn)行臟頁刷盤或者寫Checkpoint,如果這樣做還是趕不上事務(wù)執(zhí)行的速度,則為了避免數(shù)據(jù)丟失,到達(dá)sync點(diǎn)的時(shí)候,會(huì)阻塞其它所有的事務(wù),專門進(jìn)行臟頁刷盤或者寫Checkpoint。
因此從理論上來說,只要事務(wù)執(zhí)行速度大于臟頁刷盤速度,最終都會(huì)觸發(fā)日志保護(hù)機(jī)制,進(jìn)而將事務(wù)阻塞,導(dǎo)致MySQL操作掛起。
由于寫Checkpoint本身的操作相比寫臟頁要簡單,耗費(fèi)時(shí)間也要少得多,且Ckp sync點(diǎn)在Buf sync點(diǎn)之后,因此絕大部分的阻塞都是阻塞在了Buf sync點(diǎn),這也是當(dāng)事務(wù)阻塞的時(shí)候,IO很高的原因,因?yàn)檫@個(gè)時(shí)候在不斷的刷臟頁數(shù)據(jù)到磁盤。例如如下截圖的日志顯示了很多事務(wù)阻塞在了Buf sync點(diǎn):
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。