日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
圖文回顧 Redo Log 相關(guān)知識(shí)

 [[427107]]

1、如何提升 redo日志 的寫(xiě)性能?

為了保證 redo日志 不丟失,會(huì)在磁盤(pán)中開(kāi)辟一塊空間將日志保存起來(lái)。但是這樣會(huì)有一個(gè)問(wèn)題,磁盤(pán)的讀寫(xiě)性能非常的差。

長(zhǎng)葛ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書(shū)銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書(shū)合作)期待與您的合作!

所以 redo日志 和數(shù)據(jù)頁(yè)一樣,系統(tǒng)都是會(huì)分配一塊連續(xù)的內(nèi)存,來(lái)提升讀寫(xiě)性能;數(shù)據(jù)頁(yè)對(duì)應(yīng)的是 buffer pool,而 redo日志 對(duì)應(yīng)的是 log buffer。

buffer pool可以利用「innodb_buffer_pool_size」指定總大小,利用「innodb_buffer_pool_instances」指定實(shí)例數(shù),但是必須size大于等于1G才生效。

log buffer 可利用「innodb_log_buffer_size」指定 log buffer 的大小;一片連續(xù)的內(nèi)存空間會(huì)被劃分為N個(gè)512字節(jié)大小的block。

log file 可以利用「innodb_log_file_size」指定每個(gè) log file 的大小,利用「innodb_log_files_in_group」指定一共多少個(gè)log file。

2、redo日志 何時(shí)寫(xiě)入log buffer?

對(duì)底層頁(yè)面(可能是多個(gè)頁(yè)面)進(jìn)行一次原子性訪問(wèn),等于一個(gè)MTR,即 Mini Transaction。一個(gè) MTR對(duì)應(yīng)一組 redo日志 。一個(gè)事務(wù)對(duì)應(yīng)多個(gè)語(yǔ)句,一個(gè)語(yǔ)句對(duì)應(yīng)多個(gè)個(gè)MTR,一個(gè)MTR對(duì)應(yīng)一組redo日志,即多個(gè) redo日志 。

在MTR結(jié)束后,會(huì)將一組 redo日志 寫(xiě)入到log buffer中。

詳情可看下圖:

3、log buffer 中的 redo日志 何時(shí)刷盤(pán)?

  • 當(dāng) log buffer 已經(jīng)被寫(xiě)入約一半左右,下次再寫(xiě)入 redo日志 時(shí),需將 log buffer 的 redo日志 刷到磁盤(pán)文件中。
  • 當(dāng)事務(wù)結(jié)束時(shí),需先將 log buffer 中,被修改的緩存頁(yè)對(duì)應(yīng)的 redo日志 刷回磁盤(pán)中。
  • 后臺(tái)線程刷,大概每隔一秒刷一次 log buffer 中的 redo日志 到磁盤(pán)中。
  • 執(zhí)行checkpoint。
  • 正常關(guān)閉服務(wù)器。

4、我們都知道每次寫(xiě)入 redo日志 ,都是以組為單位,那么我們?cè)趺粗滥男┦且唤M?

  • 在該組中的最后一條 redo日志 后邊加上一條特殊類型的 redo日志 ,該類型名稱為「MLOG_MULTI_REC_END」,type字段對(duì)應(yīng)的十進(jìn)制數(shù)字為31,該類型的 redo日志 結(jié)構(gòu)很簡(jiǎn)單,只有一個(gè)type字段。

5、如何知道下一次redo日志改寫(xiě)到log buffer的哪個(gè)位置?

  • buf_free全局變量,指向log buffer中下個(gè)寫(xiě)入的位置。

6、如何知道下次從log buffer的哪個(gè)位置開(kāi)始刷入磁盤(pán)?

buf_next_to_write全局變量,指向log buffer中下個(gè)刷回磁盤(pán)的位置。

7、如何定位 log buffer 中的 redo日志 對(duì)應(yīng)哪些被修改的數(shù)據(jù)頁(yè);在被修改的數(shù)據(jù)頁(yè)中,如何定位到對(duì)應(yīng)的是哪些 redo日志 ?

  • 修改的緩存頁(yè)找到對(duì)應(yīng)的 redo日志
    • 當(dāng) MTR 結(jié)束時(shí),會(huì)將被修改過(guò)的數(shù)據(jù)頁(yè)對(duì)應(yīng)的數(shù)據(jù)塊放入 flush鏈表 的表頭中,并且給兩個(gè)參數(shù)賦值,分別是 old_modification 和 new_modification:old_m 賦值是 MTR 開(kāi)始前的 lsn 值,而 new_m 賦值是 MTR 結(jié)束時(shí)的 lsn 值。
    • 如果一個(gè) MTR 修改的數(shù)據(jù)頁(yè)對(duì)應(yīng)的控制塊本來(lái)就在 flush鏈表 中,則不調(diào)整數(shù)據(jù)頁(yè)對(duì)應(yīng)的數(shù)據(jù)塊的位置,只是修改 new_modification 的值,old_modification還 是保持第一次進(jìn)入 flush鏈表 時(shí) lsn 的值。
    • 就是說(shuō),在 flush鏈表 中,數(shù)據(jù)塊是根據(jù)第一次修改的時(shí)間進(jìn)行倒序排列的。
    • 首先,出場(chǎng)一個(gè)變量,叫l(wèi)sn,全稱:log sequence number,日志序列號(hào)。它記錄的是,redo日志 的總字節(jié)數(shù),初始值為8704。當(dāng)系統(tǒng)啟動(dòng),初始化log buffer 時(shí),lsn 值為 8704+12(一個(gè)log block header)=8716
    • 接著,log buffer 是由多個(gè)block組成的(可以理解為buffer pull的緩存頁(yè)),block由三部分組成,log block header(12個(gè)字節(jié))、log block body、log block trailer(4個(gè)字節(jié))。
    • 當(dāng)?shù)谝粋€(gè) redo日志 組,如「mt_1」準(zhǔn)備被寫(xiě)入,并且一個(gè)block能容納,此時(shí)lsn為 8704+12(一個(gè)log block header)=8716,假設(shè)「mt_1」一共100字節(jié),那么「mt_1」寫(xiě)入后,lsn為8716+100=8816
    • 當(dāng)?shù)诙€(gè) redo日志 組,如「mt_2」準(zhǔn)備被寫(xiě)入,并且需要跨block才能容納,如跨一個(gè)(即包含一個(gè)log block header和一個(gè)log block trailer),開(kāi)始寫(xiě)入前l(fā)sn:8816,假設(shè)「mt_2」一共1000個(gè)字節(jié),那么「mt_2」寫(xiě)入后,lsn為8816+12(一個(gè)log header)+4(一個(gè)log tail)+1000=9832
    • lsn
    • flush和lsn
    • 通過(guò)上面,那么我們可以根據(jù)flush鏈表中,數(shù)據(jù)塊的 old_modification 和 new_modification 找到對(duì)應(yīng)的一組 redo日志 ,因?yàn)橥ㄟ^(guò) lsn 可以定位到對(duì)應(yīng) redo日志 在磁盤(pán)文件中的偏移量(這個(gè)下面會(huì)講解到)。
  • redo日志 找到對(duì)應(yīng)的緩存頁(yè)面
    • redo日志 的通用結(jié)構(gòu)是:type-spaceId ID-page Number-data,即我們可以根據(jù) redo日志 的 space ID 和 page Number 即可找到對(duì)應(yīng)的緩存頁(yè)。
    • 順帶一提:在 InnoDB 中,有一個(gè)哈希表,key為表空間號(hào)+頁(yè)號(hào),value為緩存頁(yè)地址。這樣我們可以通過(guò) space ID 和 page Number 快速定位到對(duì)應(yīng)的緩存頁(yè)。

8、我們知道可以利用 lsn 知道有多少字節(jié)數(shù)的 redo日志 寫(xiě)入到 log buffer 中,那么我們能有變量對(duì)應(yīng)的知道有多少字節(jié)數(shù)的 redo日志 被刷入磁盤(pán)中嗎?

  • flushed_to_disk_lsn 全局變量,表示刷到磁盤(pán)的日志量。

9、lsn 和 log file 的偏移量怎么對(duì)得上么?

  • lsn 初始值是 8704,隨著 redo日志 的不斷寫(xiě)入,lsn 不斷增大。而 innodb 中,是利用 block 這個(gè)結(jié)構(gòu)來(lái)存儲(chǔ) redo日志 (不管是 log buffer 還是 log file),而 block 包含三部分,上面已經(jīng)提到。當(dāng) redo日志 不斷寫(xiě)入,不斷占用 block 的空間,那么 lsn 會(huì)增加對(duì)應(yīng)的字節(jié)數(shù),當(dāng)然了,除了body、也算 header 和 trailer。
  • log file 是由日志組組成,日志組最大設(shè)置100個(gè)文件數(shù),每個(gè)日志文件也是由多個(gè)512字節(jié)的block鏡像組成,日志組第一個(gè)日志文件前4個(gè)block鏡像用于存儲(chǔ)重要信息、如checkpoint等、即前2048個(gè)字節(jié)不用于存儲(chǔ) redo日志 ,即從2048個(gè)字節(jié)開(kāi)始計(jì)算 redo日志 的存放量。
  • log file 的 log file header 中有一個(gè)「LOG_HEADER_START_LSN」屬性,標(biāo)記本 redo日志 文件偏移量2048字節(jié)處對(duì)應(yīng)的lsn值。

詳情可看下圖:

10、log buffer 中的 redo日志 真的會(huì)在事務(wù)結(jié)束時(shí)立馬刷回到磁盤(pán)中嗎?

  • 默認(rèn)是的,這里有一個(gè)參數(shù)控制:「innodb_flushing_log_at_trx_commit」,默認(rèn)值是1
    • 0:事務(wù)提交,不會(huì)立馬刷到磁盤(pán)中,依賴后臺(tái)線程刷入,即如果此時(shí)MySQL或系統(tǒng)掛掉重啟,無(wú)法恢復(fù)臟頁(yè)
    • 1:事務(wù)提交,會(huì)立馬將log buffer的 redo日志 刷回磁盤(pán)中
    • 2:事務(wù)提交,會(huì)立馬將log buffer的 redo日志 刷到操作系統(tǒng)的緩存中,而不是刷到磁盤(pán)中;如果此時(shí)MySQL掛掉了,重啟后不會(huì)影響恢復(fù)臟頁(yè),而如果是系統(tǒng)掛掉,就無(wú)力回天了。

11、log file 都是循環(huán)使用,即可以覆蓋,那么怎么判斷是否可以覆蓋?

  • log file 中可被覆蓋,那么首要條件就是 redo日志 對(duì)應(yīng)的臟頁(yè)已經(jīng)被刷到磁盤(pán)中。
  • innodb 有個(gè)全局變量:checkpoint_lsn,它記錄的是可被覆蓋的 redo日志量。初始值就是lsn的初始值,8704。
    • 當(dāng)有臟頁(yè)被刷到磁盤(pán)時(shí),首先在flus鏈表中拿到最舊的緩存頁(yè),即需要拿到鏈表尾部的控制塊,然后拿到 old_modification 的值,然后將這個(gè)值賦值給 checkpoint_lsn,因?yàn)橹灰切∮?flush 鏈表中最舊的控制塊的 old_modification 的 lsn,就代表可以被覆蓋,畢竟對(duì)應(yīng)的臟頁(yè)已經(jīng)被刷到磁盤(pán)中了。
    • 接著,將根據(jù)當(dāng)前的 checkpoint_lsn 獲取對(duì)應(yīng)日志文件組的偏移量,記錄為 checkpoint_offset,checkpoint_no 也需要加1,最后將三個(gè)信息記錄在日志文件組的 checkpoint1 或 checkpoint2(checkpoint_no為奇數(shù)存1,否則存2)。
    • 上面兩步稱為執(zhí)行一次checkpoint。
    • 什么是 checkpoint?
  • 我們只需要從日志文件組中的 checkpoint1 和 checkpoint2 拿到信息,然后對(duì)比 checkpoint_no 看哪個(gè)是最新的,接著拿到checkpoint_lsn,那么 lsn 小于 checkpoint_lsn 的日志都可以被覆蓋。

12、系統(tǒng)崩潰重啟,如何利用 redo日志 進(jìn)行恢復(fù)?

  • redo日志 進(jìn)行崩潰恢復(fù)主要是利用上面提到的 checkpoint_lsn,因?yàn)?checkpoint_lsn 表示可以覆蓋的日志量,則表示 checkpoint_lsn 之前的 redo日志 對(duì)應(yīng)的臟頁(yè)都已經(jīng)被刷回到磁盤(pán)中。
  • 首先從 redo 日志組中拿到 checkpoint1 和 checkpoint2,接著判斷誰(shuí)的 checkpoint_no 大,大的就是最新的一次 checkpoint 執(zhí)行。
  • 接著拿到對(duì)應(yīng)的 checkpoint_offset,那么 checkpoint_offset 后的 redo日志 都需要掃描一遍,然后根據(jù) redo日志 的內(nèi)容,對(duì)數(shù)據(jù)頁(yè)進(jìn)行恢復(fù)。

13、恢復(fù)是掃描一個(gè) redo日志 ,就進(jìn)行一次恢復(fù)嗎?

  • 問(wèn)題:
    • 因?yàn)楦鶕?jù) redo日志 恢復(fù)數(shù)據(jù)頁(yè)的變更,是直接更新磁盤(pán)中的數(shù)據(jù)頁(yè);掃描一個(gè) redo日志 ,就進(jìn)行一次恢復(fù),如果存在多個(gè) redo日志 記錄同一個(gè)數(shù)據(jù)頁(yè)的變更,并且不是連續(xù)的,那么會(huì)導(dǎo)致多次隨機(jī)IO,性能會(huì)非常的差。
  • 解決:
    • 所以會(huì)有一個(gè)哈希表,key為 space ID + page Number,value 為數(shù)據(jù)頁(yè)地址。掃描 redo日志 時(shí),會(huì)將同一個(gè) space ID + page Number 的 redo日志 都放在同一個(gè)槽下。
    • 接著遍歷哈希表,執(zhí)行每一個(gè) space ID + page Number 對(duì)應(yīng)所有的 redo日志 。
  • 好處:
    • 避免了多次的隨機(jī)IO,提升恢復(fù)的速度。
    • 按順序根據(jù) redo日志 進(jìn)行恢復(fù),避免出現(xiàn)恢復(fù)的順序問(wèn)題。

詳情可看下圖:

14、恢復(fù)時(shí),如何知道什么時(shí)候結(jié)束?

  • 首先,我們知道,在日志組里,有多個(gè)block鏡像,然后 redo日志 刷盤(pán),是按順序填入每個(gè)block的,只有前一個(gè)block填滿了,才接著填下一個(gè)
  • 接著,每個(gè) block 的大小都是 512 個(gè)字節(jié),包括 log block header、log block body 和 log block trailer。在block的頁(yè)面結(jié)構(gòu)中,log block header 頭部有一個(gè)「LOG_BLOCK_HDR_DATA_LEN」的屬性,該屬性值記錄了當(dāng)前block里使用了多少字節(jié)的空間。對(duì)于被填滿的block來(lái)說(shuō),該值永遠(yuǎn)為512。
  • 最后,所以只管往后面一直掃,直到 log block header 中 「LOG_BLOCK_HDR_DATA_LEN」屬性不是512的 block,那么就是恢復(fù)的終點(diǎn)了。

15、如何兼容臟頁(yè)已經(jīng)已經(jīng)刷回磁盤(pán),但是 redo日志 沒(méi)有刷回磁盤(pán)的場(chǎng)景?

  • 場(chǎng)景復(fù)現(xiàn):
    • 當(dāng)我們提交事務(wù)時(shí),會(huì)根據(jù)參數(shù)「innodb_flush_at_trx_commit」來(lái)做下一步操作,如果是0或者2,那么此時(shí)的日志并沒(méi)有刷回到磁盤(pán)中,而是留在log buffer中或操作系統(tǒng)緩存中。
    • 接著,如果有后臺(tái)線程將 LRU 鏈表或 flush 鏈表的某些臟頁(yè)刷回磁盤(pán)中,刷回后;但是此時(shí)對(duì)應(yīng)的 redo日志 還停留在上面提到的兩個(gè)地方,如果服務(wù)器宕機(jī),那么對(duì)應(yīng)的 redo日志 就會(huì)丟失了。
    • 因?yàn)樗?LRU 鏈表、flush 鏈表和刷 redo日志 的后臺(tái)線程,往往都是不同的線程,無(wú)法知道對(duì)應(yīng)的 redo日志 是否已經(jīng)刷回去。
  • 兼容:
    • 每個(gè)數(shù)據(jù)頁(yè)都有一個(gè)稱之為 File Header 的部分,在 File Header 里有一個(gè)稱之為 FIL_PAGE_LSN 的屬性,該屬性記載了最近一次修改頁(yè)面時(shí)對(duì)應(yīng)的 lsn 值(其實(shí)就是頁(yè)面控制塊中的 newest_modification 值)。
    • 如果在做了某次 checkpoint 之后有臟頁(yè)被刷新到磁盤(pán)中,那么該頁(yè)對(duì)應(yīng)的 FIL_PAGE_LSN 代表的 lsn 值肯定大于 checkpoint_lsn 的值,凡是符合這種情況的頁(yè)面就不需要重復(fù)執(zhí)行 lsn 值小于 FIL_PAGE_LSN 的 redo日志 了,

當(dāng)前標(biāo)題:圖文回顧 Redo Log 相關(guān)知識(shí)
標(biāo)題來(lái)源:http://www.dlmjj.cn/article/ccsjdio.html