MySql--redo日志(下)---WAL

具體細(xì)節(jié) 請(qǐng)去掘金購(gòu)買《MySQL 是怎樣運(yùn)行的:從根兒上理解 MySQL》

redo日志刷盤時(shí)機(jī)

  • 1.當(dāng)MTR產(chǎn)生的一組redo日志在mtr結(jié)束的時(shí)候會(huì)被復(fù)制到log buffer里面
  • 2.mtr是在對(duì)應(yīng)的語(yǔ)句執(zhí)行完畢時(shí)候結(jié)束
  • 3.log buffer刷入磁盤的時(shí)機(jī)分為以下幾種:

4.log buffer 空間不足

  • 1.通過(guò)系統(tǒng)變量innodb_log_buffer_size指定 logbuffer的大小
  • 2.當(dāng)redo日質(zhì)量占滿了log buffer一半就需要把日志刷新到磁盤上(可能會(huì)存在事務(wù)未提交恤左,但是也被刷新到磁盤)

5.事務(wù)提交

  • 1.在事務(wù)提交的時(shí)候需要同步把log buffer刷新到磁盤飞袋,才能保證事務(wù)的持久性

6.后臺(tái)線程不停的刷

  • 1.后臺(tái)還有線程,每秒刷新一次log buffer中的日志到磁盤

7.正常關(guān)閉服務(wù)器的時(shí)候

8.check point時(shí)候

redo日志文件組

  • 1.在mysql的數(shù)據(jù)目錄下默認(rèn)有ib_logfile0和ib_logfile1的文件物咳,這就是對(duì)應(yīng)的redo日志文件
  • 2.通過(guò)系統(tǒng)變量innodb_log_group_home_dir指定了redo日志文件所在的目錄
  • 3.通過(guò)系統(tǒng)變量innodb_log_file_size指定了每個(gè)redo日志文件的大小蹄皱,在MySQL 5.7.21這個(gè)版本中的默認(rèn)值為48MB
  • 4.通過(guò)系統(tǒng)變量innodb_log_files_in_group指定redo日志文件的個(gè)數(shù),默認(rèn)值為2压鉴,最大值為100锻拘。
  • 5.總共的redo日志文件大小其實(shí)就是:innodb_log_file_size × innodb_log_files_in_group。
  • 6.redo日志文件組婉宰,都是循環(huán)寫入推穷,一個(gè)文件寫滿了就寫下一個(gè),寫到結(jié)尾繼續(xù)循環(huán)(從redo日志文件的第2048個(gè)字節(jié)開(kāi)始)寫入(當(dāng)然會(huì)把一些事物修改的結(jié)果落入數(shù)據(jù)頁(yè)才可以覆蓋)

redo日志文件格式

  • 1.redo日志文件和redo日志分配的block大小相同
  • 2.redo日志文件組的每個(gè)文件大小都一樣馒铃,格式也一樣都是由下面兩部分組成
  • 3.前2048個(gè)字節(jié)(也就是4個(gè)block)用來(lái)存在一些管理信息的
  • 4.從第2048個(gè)字節(jié)往后是用來(lái)存儲(chǔ)logbuffer中的block
  • 5.所以每次循環(huán)使用是從2048個(gè)字節(jié)開(kāi)始

redo日志文件的前四個(gè)block

  • 1.log file header:描述該redo日志文件的一些整體屬性
  • 2.checkpoint1:記錄關(guān)于checkpoint的一些屬性
  • 3.沒(méi)用
  • 4.checkpoint2

log file header

  • 1.LOG_HEADER_FORMAT: redo日志的版本区宇,在MySQL 5.7.21中該值永遠(yuǎn)為1
  • 2.LOG_HEADER_START_LSN:標(biāo)記本redo日志文件開(kāi)始的LSN值,也就是文件偏移量為2048字節(jié)初對(duì)應(yīng)的LSN值
  • 3.LOG_HEADER_CREATOR:一個(gè)字符串炉爆,標(biāo)記本redo日志文件的創(chuàng)建者是誰(shuí)。正常運(yùn)行時(shí)該值為MySQL的版本號(hào)
  • 4.LOG_BLOCK_CHECKSUM:本block的校驗(yàn)值
  • 5.LOG_HEADER_PAD1:做字節(jié)填充用的

checkpoint1和checkpoint2的屬性結(jié)構(gòu)

  • 1.LOG_CHECKPOINT_NO:服務(wù)器做checkpoint的編號(hào)芬首,每做一次checkpoint,該值就加1
  • 2.LOG_CHECKPOINT_LSN:服務(wù)器做checkpoint結(jié)束時(shí)對(duì)應(yīng)的LSN值,系統(tǒng)奔潰恢復(fù)時(shí)將從該值開(kāi)始
  • 3.LOG_CHECKPOINT_OFFSET:上個(gè)屬性中的LSN值在redo日志文件組中的偏移量
  • 4.LOG_CHECKPOINT_LOG_BUF_SIZE: 服務(wù)器在做checkpoint操作時(shí)對(duì)應(yīng)的log buffer的大小
  • 5.LOG_BLOCK_CHECKSUM:本block的校驗(yàn)值

Log Sequeue Number(日志序列號(hào))

  • 1.InnoDB為記錄已經(jīng)寫入的redo日志量艺晴,設(shè)計(jì)了一個(gè)稱之為L(zhǎng)og Sequeue Number的全局變量
  • 2.LSN的初始值為8704
  • 3.統(tǒng)計(jì)log buffer寫入到redo日志的量,不僅僅包含日志本身封寞,還包含log block header和log block trailer
  • 4.每一組由mtr生成的redo日志都有一個(gè)唯一的LSN值與其對(duì)應(yīng)仅财,LSN值越小,說(shuō)明redo日志產(chǎn)生的越早

flushed_to_disk_lsn

  • 1.全局變量buf_next_to_write標(biāo)志著log buffer 中已經(jīng)有哪些日志被刷新到磁盤中
  • 2.flushed_to_disk_lsn代表刷新到磁盤中的redo日志量的全局變量--該變量的值和初始的lsn值是相同的抖锥,都是8704
  • 3.如果LSN和flushed_to_disk_lsn如果兩者的值相同時(shí)碎罚,說(shuō)明log buffer中的所有redo日志都已經(jīng)刷新到磁盤中了。
  • 4.其實(shí)只有當(dāng)系統(tǒng)執(zhí)行了fsync函數(shù)后荆烈,flushed_to_disk_lsn的值才會(huì)跟著增長(zhǎng),當(dāng)僅僅把log buffer中的日志寫入到操作系統(tǒng)緩沖區(qū)卻沒(méi)有顯式的刷新到磁盤時(shí)宫峦,另外的一個(gè)稱之為write_lsn的值跟著增長(zhǎng)

lsn值和redo日志文件偏移量的對(duì)應(yīng)關(guān)系

flush鏈表中的LSN

  • 1.在mtr結(jié)束時(shí),把在mtr執(zhí)行過(guò)程中可能修改過(guò)的頁(yè)面加入到Buffer Pool的flush鏈表
  • 2.flush鏈表中的臟頁(yè)是按照頁(yè)面的第一次修改時(shí)間從大到小進(jìn)行排序的
  • 3.緩存頁(yè)對(duì)應(yīng)的控制塊中記錄兩個(gè)關(guān)于頁(yè)面何時(shí)修改的屬性:oldest_modification和newest_modification
  • 4.oldest_modification:如果某個(gè)頁(yè)面被加載到Buffer Pool后進(jìn)行第一次修改导绷,那么就將修改該頁(yè)面的mtr開(kāi)始時(shí)對(duì)應(yīng)的lsn值寫入這個(gè)屬性
  • 5.newest_modification:每修改一次頁(yè)面屎飘,都會(huì)將修改該頁(yè)面的mtr結(jié)束時(shí)對(duì)應(yīng)的lsn值寫入這個(gè)屬性。也就是說(shuō)該屬性表示頁(yè)面最近一次修改后對(duì)應(yīng)的系統(tǒng)lsn值
  • 6.flush鏈表中的臟頁(yè)按照修改發(fā)生的時(shí)間順序進(jìn)行排序枚碗,也就是按照oldest_modification代表的LSN值進(jìn)行排序,被多次更新的頁(yè)面不會(huì)重復(fù)插入到flush鏈表中遵堵,但是會(huì)更新newest_modification屬性的值

checkpoint

  • 1.判斷某些redo日志占用的磁盤空間是否可以覆蓋的依據(jù)就是它對(duì)應(yīng)的臟頁(yè)是否已經(jīng)刷新到磁盤里
  • 2.checkpoint_lsn:代表當(dāng)前系統(tǒng)中可以被覆蓋的redo日志總量是多少,這個(gè)變量初始值也是8704锡足。
  • 3.增加checkpoint_lsn就是叫checkpoint

步驟一:計(jì)算一下當(dāng)前系統(tǒng)中可以被覆蓋的redo日志對(duì)應(yīng)的lsn值最大是多少壳坪。

  • 1.尋找最早修改的臟頁(yè)對(duì)應(yīng)的oldest_modification--只要查看flush鏈表最后一個(gè)頁(yè)面的oldest_modification
  • 2.那凡是在系統(tǒng)lsn值小于該節(jié)點(diǎn)的oldest_modification值時(shí)產(chǎn)生的redo日志都是可以被覆蓋掉的
  • 3.我們就把該臟頁(yè)的oldest_modification賦值給checkpoint_lsn。

步驟二:將checkpoint_lsn和對(duì)應(yīng)的redo日志文件組偏移量以及此次checkpint的編號(hào)寫到日志文件的管理信息(就是checkpoint1或者checkpoint2)中沐批。

  • 1.InnoDB維護(hù)了一個(gè)目前系統(tǒng)做了多少次checkpoint的變量checkpoint_no
  • 2.關(guān)于checkpoint的信息只會(huì)被寫到日志文件組的第一個(gè)日志文件的管理信息中
  • 3.當(dāng)checkpoint_no的值是偶數(shù)時(shí)蝎亚,就寫到checkpoint1中,是奇數(shù)時(shí)躺彬,就寫到checkpoint2中

批量從flush鏈表中刷出臟頁(yè)

  • 1.一般情況下都是后臺(tái)的線程在對(duì)LRU鏈表和flush鏈表進(jìn)行刷臟操作
  • 2.如果后臺(tái)的刷臟操作不能將臟頁(yè)刷出梅惯,那么系統(tǒng)無(wú)法及時(shí)做checkpoint,可能就需要用戶線程同步的從flush鏈表中把那些最早修改的臟頁(yè)(oldest_modification最小的臟頁(yè))刷新到磁
  • 3.上述情況導(dǎo)致這些臟頁(yè)對(duì)應(yīng)的redo日志就沒(méi)用了江解,然后就可以去做checkpoint了徙歼。

查看系統(tǒng)中的各種LSN值

  • 1.使用SHOW ENGINE INNODB STATUS命令查看當(dāng)前InnoDB存儲(chǔ)引擎中的各種LSN值的情況
  • 2.Log sequence number:代表系統(tǒng)中的lsn值,也就是當(dāng)前系統(tǒng)已經(jīng)寫入的redo日志量桨螺,包括寫入log buffer中的日志
  • 3.Log flushed up to:代表flushed_to_disk_lsn的值酿秸,也就是當(dāng)前系統(tǒng)已經(jīng)寫入磁盤的redo日志量
  • 4.Pages flushed up to:代表flush鏈表中被最早修改的那個(gè)頁(yè)面對(duì)應(yīng)的oldest_modification屬性值
  • 5.Last checkpoint at:當(dāng)前系統(tǒng)的checkpoint_lsn值。

innodb_flush_log_at_trx_commit

  • 1.為了保證事務(wù)的持久性辣苏,用戶線程在事務(wù)提交時(shí)需要將該事務(wù)執(zhí)行過(guò)程中產(chǎn)生的所有redo日志都刷新到磁盤上
  • 2.但是1會(huì)降低數(shù)據(jù)庫(kù)性能,如果對(duì)事務(wù)的持久性要求不是那么清冽可以修改innodb_flush_log_at_trx_commit
  • 3.innodb_flush_log_at_trx_commit=0:當(dāng)該系統(tǒng)變量值為0時(shí)煌张,表示在事務(wù)提交時(shí)不立即向磁盤中同步redo日志退客,這個(gè)任務(wù)是交給后臺(tái)線程做的
  • 4.innodb_flush_log_at_trx_commit=1(默認(rèn)):表示在事務(wù)提交時(shí)需要將redo日志同步到磁盤链嘀,可以保證事務(wù)的持久性
  • 5.innodb_flush_log_at_trx_commit=2:表示在事務(wù)提交時(shí)需要將redo日志寫到操作系統(tǒng)的緩沖區(qū)中怀泊,但并不需要保證將日志真正的刷新到磁盤误趴,需要OS自己控制

崩潰恢復(fù)

確定恢復(fù)的起點(diǎn)

  • 1.checkpoint_lsn之后的都是(有可能)未刷入磁盤的,所以需要解析這部分redo日志
  • 2.redo日志文件組的第一個(gè)文件的管理信息中有兩個(gè)block都存儲(chǔ)了checkpoint_lsn的信息凉当,我們當(dāng)然是要選取最近發(fā)生的那次checkpoint的信息--通過(guò)checkpoint_no比較
  • 3.這樣我們就能拿到最近發(fā)生的checkpoint對(duì)應(yīng)的checkpoint_lsn值以及它在redo日志文件組中的偏移量checkpoint_offset。

確定恢復(fù)的終點(diǎn)

  • 1.普通block的log block header部分有一個(gè)稱之為L(zhǎng)OG_BLOCK_HDR_DATA_LEN的屬性纤怒,該屬性值記錄了當(dāng)前block里使用了多少字節(jié)的空間
  • 2.對(duì)于被填滿的block來(lái)說(shuō)泊窘,該值永遠(yuǎn)為512像寒。如果該屬性的值不為512,那么就是它了诺祸,它就是此次奔潰恢復(fù)中需要掃描的最后一個(gè)block。

怎么恢復(fù)

  • 1.使用哈希表:根據(jù)redo日志的space ID和page number屬性計(jì)算出散列值憔鬼,把space ID和page number相同的redo日志放到哈希表的同一個(gè)槽里
    胃夏,如果有多個(gè)space ID和page number都相同的redo日志,那么它們之間使用鏈表連接起來(lái)照雁,按照生成的先后順序鏈接起來(lái)的
  • 2.之后就可以遍歷哈希表答恶,因?yàn)閷?duì)同一個(gè)頁(yè)面進(jìn)行修改的redo日志都放在了一個(gè)槽里,所以可以一次性將一個(gè)頁(yè)面修復(fù)好(避免了很多讀取頁(yè)面的隨機(jī)IO)污呼,這樣可以加快恢復(fù)速度
  • 3.另外需要注意一點(diǎn)的是,同一個(gè)頁(yè)面的redo日志是按照生成時(shí)間順序進(jìn)行排序的曙求,所以恢復(fù)的時(shí)候也是按照這個(gè)順序進(jìn)行恢復(fù),如果不按照生成時(shí)間順序進(jìn)行排序的話静浴,那么可能出現(xiàn)錯(cuò)誤挤渐。比如原先的修改操作是先插入一條記錄,再刪除該條記錄
    得问,如果恢復(fù)時(shí)不按照這個(gè)順序來(lái)软免,就可能變成先刪除一條記錄,再插入一條記錄漓骚,這顯然是錯(cuò)誤的
  • 4.跳過(guò)已經(jīng)刷新到磁盤的頁(yè)面:因?yàn)閏heckpoint_lsn之后的redo日志我們不能確定是否已經(jīng)刷到磁盤
  • 5.通過(guò)頁(yè)面的File Header的FIL_PAGE_LSN屬性:記載了最近一次修改頁(yè)面時(shí)對(duì)應(yīng)的lsn值(其實(shí)就是頁(yè)面控制塊中的newest_modification值)
  • 6.如果在做了某次checkpoint之后有臟頁(yè)被刷新到磁盤中榛泛,那么該頁(yè)對(duì)應(yīng)的FIL_PAGE_LSN代表的lsn值肯定大于checkpoint_lsn的值,凡是符合這種情況的頁(yè)面就不需要重復(fù)執(zhí)行l(wèi)sn值小于FIL_PAGE_LSN的redo日志了

恢復(fù)策略

  • 1.前面說(shuō)到未提交的事務(wù)和回滾了的事務(wù)也會(huì)記錄Redo Log孤个,因此在進(jìn)行恢復(fù)時(shí),這些事務(wù)要進(jìn)行特殊的
    的處理.有2中不同的恢復(fù)策略:
    A. 進(jìn)行恢復(fù)時(shí)沛简,只重做已經(jīng)提交了的事務(wù)。
    B. 進(jìn)行恢復(fù)時(shí)佳遂,重做所有事務(wù)包括未提交的事務(wù)和回滾了的事務(wù)。然后通過(guò)Undo Log回滾那些未提交的事務(wù)丑罪。
  • 2.innodb選擇B策略

LOG_BLOCK_HDR_NO是如何計(jì)算的

  • 1.在log block header處有一個(gè)稱之為L(zhǎng)OG_BLOCK_HDR_NO的屬性
  • 2.這個(gè)屬性代表一個(gè)唯一的標(biāo)號(hào)凤壁。這個(gè)屬性是初次使用該block時(shí)分配的,跟當(dāng)時(shí)的系統(tǒng)lsn值有關(guān)
  • 3.具體公司如下:((lsn / 512) & 0x3FFFFFFFUL) + 1煤搜,0x3FFFFFFFUL代表32位比特中前兩位是0后30位是1
  • 4.讓一個(gè)數(shù)和0x3FFFFFFFUL做與運(yùn)算的意思就是要將該值的前2個(gè)比特位的值置為0,這樣該值就肯定小于或等于0x3FFFFFFFUL了
  • 5.這也就說(shuō)明了唧席,不論lsn多大嘲驾,((lsn / 512) & 0x3FFFFFFFUL)的值肯定在0~0x3FFFFFFFUL之間
  • 6.LOG_BLOCK_HDR_NO的第一個(gè)比特位比較特殊辽故,成為flushbit腐碱,如果為1代表本block是在某次將log buffer中的block刷新到磁盤的操作中的第一個(gè)被刷入的block
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末症见,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芋肠,更是在濱河造成了極大的恐慌遵蚜,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谬晕,死亡現(xiàn)場(chǎng)離奇詭異碘裕,居然都是意外死亡携取,警方通過(guò)查閱死者的電腦和手機(jī)攒钳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雷滋,“玉大人不撑,你說(shuō)我怎么就攤上這事∥钫叮” “怎么了焕檬?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)澳泵。 經(jīng)常有香客問(wèn)我实愚,道長(zhǎng),這世上最難降的妖魔是什么腊敲? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任碰辅,我火速辦了婚禮没宾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铲敛。我一直安慰自己原探,他們只是感情好咽弦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布型型。 她就那樣靜靜地躺著闹蒜,像睡著了一般绷落。 火紅的嫁衣襯著肌膚如雪砌烁。 梳的紋絲不亂的頭發(fā)上函喉,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天管呵,我揣著相機(jī)與錄音捐下,去河邊找鬼坷襟。 笑死啤握,一個(gè)胖子當(dāng)著我的面吹牛排抬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播番甩,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缘薛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宴胧!你這毒婦竟也來(lái)了恕齐?” 一聲冷哼從身側(cè)響起显歧,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤士骤,失蹤者是張志新(化名)和其女友劉穎拷肌,沒(méi)想到半個(gè)月后廓块,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體契沫,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年会通,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涕侈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裳涛。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舷礼,死狀恐怖郊闯,靈堂內(nèi)的尸體忽然破棺而出团赁,到底是詐尸還是另有隱情欢摄,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站嫌变,受9級(jí)特大地震影響腾啥,放射性物質(zhì)發(fā)生泄漏冯吓。R本人自食惡果不足惜组贺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一啊奄、第九天 我趴在偏房一處隱蔽的房頂上張望菇夸。 院中可真熱鬧仪吧,春花似錦、人聲如沸择诈。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)步做。三九已至全度,卻和暖如春将鸵,著一層夾襖步出監(jiān)牢的瞬間顶掉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移袍,地道東北人葡盗。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓路狮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親涂籽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子评雌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344