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

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

redo日志

row_id隱藏列賦值的方式

  • 1.服務(wù)器會(huì)在內(nèi)存中維護(hù)一個(gè)全局變量,每當(dāng)向某個(gè)包含隱藏的row_id列的表中插入一條記錄時(shí),就會(huì)把該變量的值當(dāng)作新記錄的row_id列的值,并且把該變量自增1。
  • 2.每當(dāng)這個(gè)變量的值為256的倍數(shù)時(shí),就會(huì)將該變量的值刷新到系統(tǒng)表空間的頁(yè)號(hào)為7的頁(yè)面中一個(gè)稱(chēng)之為Max Row ID的屬性處
  • 3.當(dāng)系統(tǒng)啟動(dòng)時(shí),會(huì)將上邊提到的Max Row ID屬性加載到內(nèi)存中,將該值加上256之后賦值給我們前邊提到的全局變量

邏輯日志

  • 1.簡(jiǎn)單理解記錄的是sql語(yǔ)句

物理日志

  • 1.記錄的是4元組數(shù)據(jù),哪個(gè)表空間,哪個(gè)文件,哪個(gè)頁(yè),哪個(gè)偏移位置,插入的字節(jié)內(nèi)容

邏輯物理日志

  • 1.redo日志頁(yè)面內(nèi)的操作記錄的是邏輯日志
  • 2.redo日志頁(yè)間的操作記錄的是物理日志
  • 3.binlog是邏輯日志
  • 4.redo是邏輯物理日志,所以partial page時(shí)需要double write介入才能恢復(fù)數(shù)據(jù)

partial page

  • 1.比如我們對(duì)一個(gè)頁(yè)進(jìn)行刷新操作,操作一般就斷電了。
  • 2.這個(gè)時(shí)候redo因?yàn)槭琼?yè)內(nèi)是邏輯日志,只記錄數(shù)據(jù)的邏輯,而原先的物理位置已經(jīng)被占滿(mǎn)了
  • 3.因此只能完全的替換該頁(yè)面,重新使用redo

redo日志解決了什么

  • 1.磁盤(pán)的數(shù)據(jù)被load到bufferpool之后,如果我們修改buffer pool了,這些數(shù)據(jù)不會(huì)立馬被刷入到磁盤(pán),那么如何保證事務(wù)的持久性
  • 2.如果修改了bufferpool頁(yè)面數(shù)據(jù)就需要立即刷入磁盤(pán),一個(gè)是太浪費(fèi)(一個(gè)頁(yè)有16kb,修個(gè)一個(gè)字節(jié)也刷16KB不合理),二個(gè)是隨機(jī)IO刷起來(lái)慢(因?yàn)橐粋€(gè)事務(wù)可能修改不同的頁(yè),這些頁(yè)在物理上并不一定是連續(xù)的)
  • 3.redo日志就是解決上述1和2的問(wèn)題的。

redo日志的優(yōu)點(diǎn)

  • 1.占用的空間非常?。捍鎯?chǔ)表空間ID、頁(yè)號(hào)、偏移量以及需要更新的值
  • 2.redo日志是順序?qū)懭氪疟P(pán)的

通用的redo日志格式

type

  • 1.redo日志的類(lèi)型

space ID

  • 1.表空間ID。

page number

  • 1.頁(yè)號(hào)

data

  • 1.該條redo日志的具體內(nèi)容。

簡(jiǎn)單的redo日志類(lèi)型

  • 1.比如更新Max Row ID

MLOG_XBYTE(物理日志)

  • 1.標(biāo)識(shí)在頁(yè)面的某個(gè)偏移量處寫(xiě)入了X字節(jié)的redo日志
  • 2.多了一個(gè)offset,代表需要修改記錄的起始位置

MLOG_WRITE_STRING(物理日志)

  • 1.多了一個(gè)offset和len
  • 2.len代表數(shù)據(jù)的長(zhǎng)度

復(fù)雜一些的redo日志類(lèi)型

  • 1.一個(gè)語(yǔ)句可能會(huì)更新葉子節(jié)點(diǎn),也有可能更新內(nèi)節(jié)點(diǎn),甚至于產(chǎn)生新的頁(yè)面
  • 2.還得需要更新Page Directory中的槽信息。
  • 3.Page Header中的各種頁(yè)面統(tǒng)計(jì)信息
  • 4.還需要更新上一條記錄的記錄頭信息中的next_record
  • 5.把一條記錄插入到一個(gè)頁(yè)面時(shí)需要更改的地方非常多(多個(gè)頁(yè)面)
  • 6.因此復(fù)雜的redo日志處理包含物理層面的意思,也得包含邏輯層面的意思
  • 7.物理層面看,這些日志都指明了對(duì)哪個(gè)表空間的哪個(gè)頁(yè)進(jìn)行了修改。
  • 8.邏輯層面看,在系統(tǒng)奔潰重啟時(shí),并不能直接根據(jù)這些日志里的記載,將頁(yè)面內(nèi)的某個(gè)偏移量處恢復(fù)成某個(gè)數(shù)據(jù),而是需要調(diào)用一些事先準(zhǔn)備好的函數(shù),執(zhí)行完這些函數(shù)后才可以將頁(yè)面恢復(fù)成系統(tǒng)奔潰前的樣子。

MLOG_REC_INSERT

  • 1.表示插入一條使用非緊湊行格式的記錄時(shí)的redo日志類(lèi)型。
  • 2.Redundant是一種比較原始的行格式,它就是非緊湊的

MLOG_COMP_REC_INSERT

  • 1.表示插入一條使用緊湊行格式的記錄時(shí)的redo日志類(lèi)型。
  • 2.Compact、Dynamic以及Compressed行格式是較新的行格式,它們是緊湊的
  • 3.日志結(jié)構(gòu)比通用的日志額外多了以下字段
  • 4.n_fields:記錄該記錄有多少個(gè)字段
  • 5.n_uniques:在一條記錄中,需要幾個(gè)字段的值才能確保記錄的唯一性
  • 6.fieldX_len:第X個(gè)字段的占用的存儲(chǔ)空間大小
  • 7.offset:前一條記錄的地址
  • 8.end_seg_len:從該字段可以計(jì)算出當(dāng)前記錄總共占用的存儲(chǔ)空間的大小
  • 9.info bits:記錄頭信息的前4個(gè)比特位的值以及record_type的值
  • 10.extra_size:記錄額外信息占用的存儲(chǔ)空間大小
  • 11.mismatch index:未知作用
  • 12.對(duì)于聚簇索引來(lái)說(shuō),n_uniques的值為主鍵的列數(shù),對(duì)于其他二級(jí)索引來(lái)說(shuō),該值為索引列數(shù)+主鍵列數(shù)

MLOG_COMP_PAGE_CREATE

  • 1.表示創(chuàng)建一個(gè)存儲(chǔ)緊湊行格式記錄的頁(yè)面的redo日志類(lèi)型。

MLOG_COMP_REC_DELETE

  • 1.表示刪除一條使用緊湊行格式記錄的redo日志類(lèi)型。

MLOG_COMP_LIST_START_DELETE

  • 1.表示從某條給定記錄開(kāi)始刪除頁(yè)面中的一系列使用緊湊行格式記錄的redo日志類(lèi)型。

MLOG_COMP_LIST_END_DELETE

  • 1.與MLOG_COMP_LIST_START_DELETE類(lèi)型的redo日志呼應(yīng),表示刪除一系列記錄直到MLOG_COMP_LIST_END_DELETE類(lèi)型的redo日志對(duì)應(yīng)的記錄為止。

MLOG_COMP_LIST_START_DELETE和MLOG_COMP_LIST_END_DELETE存在的意義

  • 1.數(shù)據(jù)頁(yè)中的記錄是按照索引列大小的順序組成單向鏈表的。有時(shí)候我們會(huì)有刪除索引列的值在某個(gè)區(qū)間范圍內(nèi)的所有記錄的需求,這時(shí)候如果我們每刪除一條記錄就寫(xiě)一條redo日志的話(huà),效率可能有點(diǎn)低,
    所以提出MLOG_COMP_LIST_START_DELETE和MLOG_COMP_LIST_END_DELETE類(lèi)型的redo日志,可以很大程度上減少redo日志的條數(shù)

MLOG_ZIP_PAGE_COMPRESS

  • 1.表示壓縮一個(gè)數(shù)據(jù)頁(yè)的redo日志類(lèi)型。

redo日志格式小結(jié)

Mini-Transaction

  • 1.以組的形式寫(xiě)入redo日志
  • 2.在執(zhí)行語(yǔ)句的過(guò)程中產(chǎn)生的redo日志被設(shè)計(jì)InnoDB的大叔人為的劃分成了若干個(gè)不可分割的組
  • 3.多個(gè)普通redo日志組成一個(gè)完成的redo日志,結(jié)尾是以一個(gè)type=MLOG_MULTI_REC_END結(jié)尾
  • 4.當(dāng)然只有一個(gè)redo日志也可以組成一個(gè)組,具體的看type的值
  • 5.type字段是一個(gè)字節(jié) 8個(gè)bit,第一個(gè)bit代表該組是否是單一的redo,后面7位代表了redo的日志類(lèi)型。
  • 6.對(duì)底層頁(yè)面中的一次原子訪(fǎng)問(wèn)的過(guò)程稱(chēng)之為一個(gè)Mini-Transaction--MTR
  • 7.一個(gè)事務(wù)包含若干個(gè)語(yǔ)句,一個(gè)語(yǔ)句對(duì)應(yīng)若干個(gè)mtr,一個(gè)mtr包含若干個(gè)redo

redo日志的寫(xiě)入過(guò)程

redo log block

  • 1.Innodb把mtr生成的redo日志都存放在大小為512字節(jié)的頁(yè)(block)中,該頁(yè)和表空間頁(yè)有所區(qū)別--是共享表空間
  • 2.block==log block header,log block body 和log block trailer
  • 3.log block header和log block trailer存儲(chǔ)的是一些管理信息,log block body存儲(chǔ)的是redo

log block header

  • 1.LOG_BLOCK_HDR_NO:每一個(gè)block都有一個(gè)大于0的唯一標(biāo)號(hào),本屬性就表示該標(biāo)號(hào)值。
  • 2.LOG_BLOCK_HDR_DATA_LEN:表示block中已經(jīng)使用了多少字節(jié),初始值為12(因?yàn)閘og block body從第12個(gè)字節(jié)處開(kāi)始)
  • 3.LOG_BLOCK_FIRST_REC_GROUP:代表該block中第一個(gè)mtr生成的redo日志記錄組的偏移量(其實(shí)也就是這個(gè)block里第一個(gè)mtr生成的第一條redo日志的偏移量)
  • 4.LOG_BLOCK_CHECKPOINT_NO:表示所謂的checkpoint的序號(hào)

log block trailer

  • 1.LOG_BLOCK_CHECKSUM:表示block的校驗(yàn)值,用于正確性校驗(yàn)

redo日志緩沖區(qū)

  • 1.redo日志也需要緩沖區(qū),其是在服務(wù)器啟動(dòng)時(shí)就向操作系統(tǒng)申請(qǐng)了一大片稱(chēng)之為redo log buffer的連續(xù)內(nèi)存空間
  • 2.這片內(nèi)存空間被劃分成若干個(gè)連續(xù)的redo log block
  • 3.可以通過(guò)innodb_log_buffer_size來(lái)指定log buffer的大小
  • 4.redo日志寫(xiě)入log buffer是順序的,通過(guò)全局變量buf_free來(lái)指明后續(xù)的redo日志應(yīng)該寫(xiě)入到log buffer中的哪個(gè)位置
  • 5.并不是每生成一條redo日志,就將其插入到log buffer中,而是每個(gè)mtr運(yùn)行過(guò)程中產(chǎn)生的日志先暫時(shí)存到一個(gè)地方,當(dāng)該mtr結(jié)束的時(shí)候,將過(guò)程中產(chǎn)生的一組redo日志再全部復(fù)制到log buffer中
  • 6.根據(jù)5的描述不同事務(wù)的mtr可能是交替寫(xiě)入log buffer的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容