溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析

發(fā)布時(shí)間:2020-04-27 10:41:14 來(lái)源:億速云 閱讀:1006 作者:三月 欄目:MySQL數(shù)據(jù)庫(kù)

下文內(nèi)容主要給大家?guī)?lái)redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析,這里所講到的知識(shí),與書(shū)籍略有不同,都是億速云專業(yè)技術(shù)人員在與用戶接觸過(guò)程中,總結(jié)出來(lái)的,具有一定的經(jīng)驗(yàn)分享價(jià)值,希望給廣大讀者帶來(lái)幫助。

MySQL的InnoDB存儲(chǔ)引引擎的物理文件存儲(chǔ)體系中,除了實(shí)際的數(shù)據(jù)文件(ibd, ibdata)之外,還有兩個(gè)非常重要的日志系統(tǒng),分別是redo日志和undo日志。 跟Oracle類似, redo log記錄了對(duì)實(shí)際數(shù)據(jù)文件的物理變更(數(shù)據(jù)文件的什么位置數(shù)據(jù)做了如何的變更)。InnoDB也是采用了WAL(日志優(yōu)先落盤(pán)),也就是說(shuō)在實(shí)際數(shù)據(jù)文件的修改落盤(pán)之前redo日志已經(jīng)落盤(pán),從而來(lái)保證事務(wù)的持久性。Undo日志用來(lái)保證事務(wù)的原子性和MVCC,所有的undo操作產(chǎn)身的數(shù)據(jù)文件的變更也會(huì)記錄到redo日志中。
在原生的MySQL中,redo日志不會(huì)用來(lái)做物理主從復(fù)制,其主要的應(yīng)用場(chǎng)景是用來(lái)進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))。關(guān)于MySQL InnoDB的崩潰恢復(fù)會(huì)在后續(xù)的文章中進(jìn)行介紹。

redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析


本文主要基于MySQL 8.0介紹redo Log的基本構(gòu)成。
1.    redo 日志文件
從MySQL 5.6開(kāi)始,已經(jīng)廢棄了日志組的特性(redo日志可以寫(xiě)多份),網(wǎng)上有觀點(diǎn)認(rèn)為可能是InnoDB的開(kāi)發(fā)團(tuán)隊(duì)認(rèn)為用外層的存儲(chǔ)硬件來(lái)保證日志組的完整性可能更好一些。同時(shí)從5.7開(kāi)始InnoDB的歸檔日志Archive也被放棄(歸檔日志用來(lái)歸檔存放所有的redo日志,redo日志系統(tǒng)內(nèi)是采用固定尺寸的多個(gè)log文件循環(huán)寫(xiě)的方式來(lái)存放redo日志,如果寫(xiě)滿了會(huì)循環(huán)到開(kāi)始的位置開(kāi)始寫(xiě)入)。
不過(guò)MySQL 8.0引入一個(gè)稱之為克隆的機(jī)制,從代碼的角度來(lái)看,似乎是用來(lái)實(shí)現(xiàn)遠(yuǎn)程克隆一個(gè)當(dāng)前數(shù)據(jù)庫(kù)的副本,在這個(gè)機(jī)制中又引入的新的Archive歸檔機(jī)制。如果讀者有興趣可以閱讀一下MySQL8.0新版本源碼的storage\innobase\arch和 storage\innobase\clone目錄下的代碼。
1.1.  redo Log相關(guān)參數(shù)
innodb_log_group_home_dir
該參數(shù)用來(lái)指定redo日志存放的路徑,日志文件以ib_logfile[number]來(lái)命名。
innodb_log_files_in_group
雖然MySQL已經(jīng)放棄了日志組的概念,但參數(shù)名依舊保留了下來(lái)以兼容以前的配置。該參數(shù)的含義為有多少個(gè)log文件(最少為2個(gè))。
innodb_log_file_size
表示每個(gè)文件的大小。
所以,總的redo Log的大小為 innodb_log_files_in_group * innodb_log_file_size.

1.2.  redo Log循環(huán)寫(xiě)
redo Log以順序的方式寫(xiě)入文件,當(dāng)全部文件寫(xiě)滿的時(shí)候則回到第一個(gè)文件相應(yīng)的起始位置進(jìn)行覆蓋寫(xiě)(但在做redo checkpoint時(shí),也會(huì)更新第一個(gè)日志文件的頭部checkpoint標(biāo)記,所以嚴(yán)格來(lái)講也不算順序?qū)懀?,在InnoDB內(nèi)部,邏輯上Redo Log被看作一個(gè)文件,對(duì)應(yīng)一個(gè)space id (InnoDB通過(guò)space的概念來(lái)組織物理存儲(chǔ),包括不同的表,數(shù)據(jù)字典,redo,undo等)。
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析

上圖是以指定innodb_log_files_in_group為3的循環(huán)寫(xiě)的情況。

2.    Redo Log存儲(chǔ)格式簡(jiǎn)介
盡管Redo Log有多個(gè)文件,但每個(gè)文件的組成結(jié)構(gòu)是一樣的,只是有一些數(shù)據(jù)只會(huì)存在的第一個(gè)Log文件(ib_logfile0)的文件頭中, 例如Buffer Pool flush checkpoint信息只會(huì)寫(xiě)在第一個(gè)log文件的文件頭中。
2.1.  日志文件存儲(chǔ)結(jié)構(gòu)概覽
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
(ib_logfile0 存儲(chǔ)概覽圖)

redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
(ib_logfile0 之外其它redo log文件的存儲(chǔ)概覽)
InnoDB也是采用WAL的機(jī)制來(lái)保證事務(wù)的持久性,從一定的意義上來(lái)說(shuō),redo日志是順序?qū)?,?xiě)入速度很快。數(shù)據(jù)庫(kù)事務(wù)導(dǎo)致的數(shù)據(jù)修改進(jìn)入到InnoDB存儲(chǔ)層之后會(huì)將這些修改變更的記錄存入redo log中,然后將數(shù)據(jù)的變更寫(xiě)入內(nèi)存中的Page Pool中。InnoDB的后臺(tái)線程會(huì)按照一定的規(guī)則(例如定時(shí)或者臟頁(yè)的數(shù)量達(dá)到一定的比例)將臟頁(yè)落盤(pán),落盤(pán)后會(huì)記錄下來(lái)當(dāng)前redo Log中有多少變更日志已經(jīng)實(shí)際存儲(chǔ)到了實(shí)際的數(shù)據(jù)space文件中。redo log的總的寫(xiě)入量叫LSN(Log Secquence Numer)日志序列號(hào),這個(gè)redo log變更實(shí)際寫(xiě)入到實(shí)際數(shù)據(jù)文件中的數(shù)量叫checkpoint LSN,表示的是有多少變更已經(jīng)實(shí)際寫(xiě)入到了相應(yīng)的數(shù)據(jù)文件中。 一旦數(shù)據(jù)庫(kù)崩潰InnoDB開(kāi)始恢復(fù)數(shù)據(jù)的時(shí)候,先讀取checkpoint,然后從checkpoint所指示的LSN讀取其之后的Redo日志進(jìn)行數(shù)據(jù)恢復(fù),從而減少Crash Recovery的時(shí)間。
比較前面兩個(gè)概覽圖可以看到,checkpoint信息只是存儲(chǔ)在第一個(gè)log文件頭中。同時(shí)我們看到日志頭中有2個(gè)checkpoint block域。InnoDB是采用2個(gè)checkpoint了輪流寫(xiě)的方式來(lái)保證checkpoint的安全(并不是一次寫(xiě)2份checkpoint, 而是輪流寫(xiě))。 也由于Redo log是冪等的,應(yīng)用一次和與應(yīng)用兩次都是一樣的(在實(shí)際的應(yīng)用Redo中,如果當(dāng)前這一條log的lsn大于當(dāng)前page的lsn,說(shuō)明這一條log還沒(méi)有被應(yīng)用到當(dāng)前page中去)。所以,即使某次checkpoint block寫(xiě)失敗了,那么崩潰恢復(fù)的時(shí)候從上一次記錄的checkpoint點(diǎn)開(kāi)始恢復(fù)也能正確的恢復(fù)數(shù)據(jù)庫(kù)事務(wù)。
2.2.  Log File Header
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
(Log File Header存儲(chǔ)結(jié)構(gòu))
Log Header Format:
這個(gè)字段以前用來(lái)標(biāo)識(shí)當(dāng)前Log文件屬于哪個(gè)日志組,現(xiàn)在新的意義是用來(lái)標(biāo)識(shí)當(dāng)前Log為文件的格式版本。例如如果為0則表示這個(gè)redo log是有5.7.9以前的MySQL生成的。
PAD:
沒(méi)有任何含義,目前僅僅用來(lái)做一些對(duì)齊處理。
Start LSN:
這個(gè)字段用在Clone和Archive場(chǎng)景,與一般的持久性、崩潰恢復(fù)無(wú)關(guān),這里不做討論。
Creator:
存儲(chǔ)的是創(chuàng)建這個(gè)log文件創(chuàng)建者的名稱的字符串。
Left Bytes:
目前沒(méi)有任何含義,僅僅是用來(lái)填充占位,以便讓這個(gè)block達(dá)到512字節(jié)大小。
2.3.  Log Checkpoint
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
(Checkpoint block儲(chǔ)存概覽)
checkpoint number:
checkpoint number可以理解為checkpoint域?qū)懕P(pán)的次數(shù),每次寫(xiě)盤(pán)遞增1,同時(shí)這個(gè)值取模2可以實(shí)現(xiàn)2個(gè)checkpoint域輪流寫(xiě)。
checkpoint LSN:
該字段標(biāo)示小于這個(gè)Checkpoint LSN的日志記錄都已經(jīng)寫(xiě)入到了實(shí)際的數(shù)據(jù)文件中,Crash Recovery系統(tǒng)從Checkpoint LSN之后的第一個(gè)MTR記錄開(kāi)始進(jìn)行數(shù)據(jù)恢復(fù)。
checkpoint offset:
Checkpoint LSN對(duì)應(yīng)在Log files中的文件偏移量,這個(gè)用來(lái)對(duì)LSN和Offset之間轉(zhuǎn)換進(jìn)行校準(zhǔn)。
Buf size:
MySQL系統(tǒng)內(nèi)只對(duì)該字段執(zhí)行了寫(xiě)入,并為進(jìn)行讀取然后進(jìn)行相應(yīng)的處理。它標(biāo)識(shí)的是系統(tǒng)當(dāng)前Log buffer的大小。
Left bytes:
目前沒(méi)有任何含義,僅僅是用來(lái)填充占位,以便讓這個(gè)block達(dá)到512字節(jié)大小。但在這里最后4個(gè)字節(jié)用來(lái)存放該checkpoint域的Checksum。

2.4.  Log Block的存儲(chǔ)格式
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
(Log Block的存儲(chǔ)格式)
Log Block Number:
Log Block的編號(hào),從1開(kāi)始遞增,達(dá)到最大值(0x3FFFFFFF+1)后再繼續(xù)從1開(kāi)始。
Data length:
寫(xiě)入到當(dāng)前block的字節(jié)數(shù),包含頭部12字節(jié)的大小
Firsrt Record offset
本Block內(nèi)第一個(gè)mtr記錄的起始偏移量
log Block Checkpoint number
該block所處在的checkpoint no
Log Records:
一個(gè)block內(nèi)可以存儲(chǔ)多條mtr記錄,同樣一個(gè)mtr記錄可以跨越多個(gè)block.
2.5.  redo日志邏輯格式到物理格式的映射
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
上圖是以指定innodb_log_files_in_group為2邏輯結(jié)構(gòu)到物理結(jié)構(gòu)的映射

上圖中上層的為Redolog的邏輯結(jié)構(gòu),可以看作是內(nèi)存中的log buffer, 下層的為redo Log的實(shí)際物理文件存儲(chǔ),由于版面的關(guān)系,我們以innodb_log_files_in_group為2來(lái)做示例,每個(gè)log文件中僅僅包含了2個(gè)log block(Log block的多少取決與設(shè)定的innodb_log_file_size)。
每產(chǎn)生一個(gè)mtr記錄就將其append到log buffer中去,當(dāng)log buffer落盤(pán)的時(shí)候會(huì)獲取固定大小的數(shù)據(jù)寫(xiě)入到block的數(shù)據(jù)域。當(dāng)然,如果buffer中剩余的數(shù)據(jù)不足以填滿一個(gè)block的數(shù)據(jù)域,也會(huì)將其寫(xiě)入到一個(gè)新的block中,不足的數(shù)據(jù)自動(dòng)不齊,block header中的data length字段會(huì)指出有效數(shù)據(jù)的數(shù)量。

2.6.  MTR簡(jiǎn)介
MTR即Mini-transaction的縮寫(xiě),字面意思小事物,相對(duì)邏輯事物而言,我們把它稱作物理事物。屬于Innodb存儲(chǔ)引擎的底層模塊。主要用于鎖和日志信息。InnoDB內(nèi)部的上層模塊會(huì)將事務(wù)操作轉(zhuǎn)換成若干的MTR物理事務(wù)。至于上層的事務(wù)操作如何轉(zhuǎn)換的MTR此操作,后續(xù)再另外單獨(dú)介紹,本文只介紹一下MTR記錄的格式。
每一個(gè)MTR操作會(huì)產(chǎn)身一條MTR Record, 下一小節(jié)我們會(huì)介紹一下MTR記錄的格式。
2.7.  MTR記錄格式
用一句通俗的話來(lái)講,一條MTR記錄表示的是對(duì)哪個(gè)數(shù)據(jù)文件(space id)的哪一頁(yè)(page)的頁(yè)內(nèi)某個(gè)偏移量(offset)位置做了什么改變(value).
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析

(一條MTR記錄的通用格式)
Type:
MTR記錄的類型
Space ID:
該MTR記錄修改了哪個(gè)數(shù)據(jù)文件
Page Number
該MTR記錄修改了哪一頁(yè)
Record Payload:
根據(jù)Type的不同,Payload內(nèi)容格式也不相同,大小也不相同。后面會(huì)給出一個(gè)Type為MLOG_COMP_REC_INSERT大致的存儲(chǔ)結(jié)構(gòu)。
(MTR Type - MLOG_COMP_REC_INSERT)
redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析
最后列出一些MTR Record Type, 讀者從名字應(yīng)該就能看出這個(gè)Type的含義
/ one byte is written */
MLOG_1BYTE = 1,
/* 2 bytes ... /
MLOG_2BYTES = 2,
/
4 bytes ... */
MLOG_4BYTES = 4,
/ 8 bytes ... */
MLOG_8BYTES = 8,
/* Record insert /
MLOG_REC_INSERT = 9,
/
Mark clustered index record deleted */
MLOG_REC_CLUST_DELETE_MARK = 10,
/ Mark secondary index record deleted */
MLOG_REC_SEC_DELETE_MARK = 11,
/* update of a record, preserves record field sizes /
MLOG_REC_UPDATE_IN_PLACE = 13,
/!< Delete a record from a page /
MLOG_REC_DELETE = 14,
/
Delete record list end on index page */
MLOG_LIST_END_DELETE = 15,
/ Delete record list start on index page */
MLOG_LIST_START_DELETE = 16,
/* Copy record list end to a new created index page /
MLOG_LIST_END_COPY_CREATED = 17,
/
Reorganize an index page in ROW_FORMAT=REDUNDANT */
MLOG_PAGE_REORGANIZE = 18,
/ Create an index page */
MLOG_PAGE_CREATE = 19,
/* mark a compact index record as the predefined minimum record /
MLOG_COMP_REC_MIN_MARK = 36,
/
create a compact index page */
MLOG_COMP_PAGE_CREATE = 37,
/* compact record insert /
MLOG_COMP_REC_INSERT = 38,
/* mark compact clustered index record deleted /
MLOG_COMP_REC_CLUST_DELETE_MARK = 39,

對(duì)于以上關(guān)于redo日志進(jìn)行MySQL的Crash Recovey(崩潰恢復(fù))解析,如果大家還有更多需要了解的可以持續(xù)關(guān)注我們億速云的行業(yè)推新,如需獲取專業(yè)解答,可在官網(wǎng)聯(lián)系售前售后的,希望該文章可給大家?guī)?lái)一定的知識(shí)更新。

 

 


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI