最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

MySQLredolog及recover過程淺析

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-09 19:15:13
文檔

MySQLredolog及recover過程淺析

MySQLredolog及recover過程淺析:寫在前面:作者水平有限,歡迎不吝賜教,一切以最新源碼為準。InnoDB redo log首先介紹下Innodb redo log是什么,為什么需要記錄redo log,以及redo log的作用都有哪些。這些作為常識,只是為了本文完整。InnoDB有buffer pool(簡稱bp)。b
推薦度:
導(dǎo)讀MySQLredolog及recover過程淺析:寫在前面:作者水平有限,歡迎不吝賜教,一切以最新源碼為準。InnoDB redo log首先介紹下Innodb redo log是什么,為什么需要記錄redo log,以及redo log的作用都有哪些。這些作為常識,只是為了本文完整。InnoDB有buffer pool(簡稱bp)。b
寫在前面:作者水平有限,歡迎不吝賜教,一切以最新源碼為準。

InnoDB redo log

首先介紹下Innodb redo log是什么,為什么需要記錄redo log,以及redo log的作用都有哪些。這些作為常識,只是為了本文完整。

InnoDB有buffer pool(簡稱bp)。bp是數(shù)據(jù)庫頁面的緩存,對InnoDB的任何修改操作都會首先在bp的page上進行,然后這樣的頁面將被標記為dirty并被放到專門的flush list上,后續(xù)將由master thread或?qū)iT的刷臟線程階段性的將這些頁面寫入磁盤(disk or ssd)。這樣的好處是避免每次寫操作都操作磁盤導(dǎo)致大量的隨機IO,階段性的刷臟可以將多次對頁面的修改merge成一次IO操作,同時異步寫入也降低了訪問的時延。然而,如果在dirty page還未刷入磁盤時,server非正常關(guān)閉,這些修改操作將會丟失,如果寫入操作正在進行,甚至?xí)捎趽p壞數(shù)據(jù)文件導(dǎo)致數(shù)據(jù)庫不可用。為了避免上述問題的發(fā)生,Innodb將所有對頁面的修改操作寫入一個專門的文件,并在數(shù)據(jù)庫啟動時從此文件進行恢復(fù)操作,這個文件就是redo log file。這樣的技術(shù)推遲了bp頁面的刷新,從而提升了數(shù)據(jù)庫的吞吐,有效的降低了訪問時延。帶來的問題是額外的寫redo log操作的開銷(順序IO,當然很快),以及數(shù)據(jù)庫啟動時恢復(fù)操作所需的時間。

接下來將結(jié)合MySQL 5.6的代碼看下Log文件的結(jié)構(gòu)、生成過程以及數(shù)據(jù)庫啟動時的恢復(fù)流程。

Log文件結(jié)構(gòu)

Redo log文件包含一組log files,其會被循環(huán)使用。Redo log文件的大小和數(shù)目可以通過特定的參數(shù)設(shè)置,詳見:innodb_log_file_size 和 innodb_log_files_in_group 。每個log文件有一個文件頭,其代碼在"storage/innobase/include/log0log.h"中,我們看下log文件頭都記錄了哪些信息:

669 /* Offsets of a log file header */670 #define LOG_GROUP_ID0 /* log group number */671 #define LOG_FILE_START_LSN4 /* lsn of the start of data in this672 log file */673 #define LOG_FILE_NO 12/* 4-byte archived log file number;674 this field is only defined in an675 archived log file */676 #define LOG_FILE_WAS_CREATED_BY_HOT_BACKUP 16677 /* a 32-byte field which contains678 the string 'ibbackup' and the679 creation time if the log file was680 created by ibbackup --restore;681 when mysqld is first time started682 on the restored database, it can683 print helpful info for the user */684 #define LOG_FILE_ARCH_COMPLETED OS_FILE_LOG_BLOCK_SIZE685 /* this 4-byte field is TRUE when686 the writing of an archived log file687 has been completed; this field is688 only defined in an archived log file */689 #define LOG_FILE_END_LSN(OS_FILE_LOG_BLOCK_SIZE + 4)690 /* lsn where the archived log file691 at least extends: actually the692 archived log file may extend to a693 later lsn, as long as it is within the694 same log block as this lsn; this field695 is defined only when an archived log696 file has been completely written */697 #define LOG_CHECKPOINT_1OS_FILE_LOG_BLOCK_SIZE698 /* first checkpoint field in the log699 header; we write alternately to the700 checkpoint fields when we make new701 checkpoints; this field is only defined702 in the first log file of a log group */703 #define LOG_CHECKPOINT_2(3 * OS_FILE_LOG_BLOCK_SIZE)704 /* second checkpoint field in the log705 header */706 #define LOG_FILE_HDR_SIZE (4 * OS_FILE_LOG_BLOCK_SIZE)

日志文件頭共占用4個OS_FILE_LOG_BLOCK_SIZE的大小,這里對部分字段做簡要介紹:

1. LOG_GROUP_ID 這個log文件所屬的日志組,占用4個字節(jié),當前都是0;

2. LOG_FILE_START_LSN 這個log文件記錄的初始數(shù)據(jù)的lsn,占用8個字節(jié);

3. LOG_FILE_WAS_CRATED_BY_HOT_BACKUP 備份程序所占用的字節(jié)數(shù),共占用32字節(jié),如xtrabackup在備份時會在xtrabackup_logfile文件中記錄"xtrabackup backup_time";

4. LOG_CHECKPOINT_1/LOG_CHECKPOINT_2 兩個記錄InnoDB checkpoint信息的字段,分別從文件頭的第二個和第四個block開始記錄,只使用日志文件組的第一個日志文件。

這里多說兩句,每次checkpoint后InnoDB都需要更新這兩個字段的值,因此redo log的寫入并非嚴格的順序?qū)懀?/p>

每個log文件包含許多l(xiāng)og records。log records將以O(shè)S_FILE_LOG_BLOCK_SIZE(默認值為512字節(jié))為單位順序?qū)懭雔og文件。每一條記錄都有自己的LSN(log sequence number,表示從日志記錄創(chuàng)建開始到特定的日志記錄已經(jīng)寫入的字節(jié)數(shù))。每個Log Block包含一個header段、一個tailer段,以及一組log records。

首先看下Log Block header。block header的開始4個字節(jié)是log block number,表示這是第幾個block塊。其是通過LSN計算得來,計算的函數(shù)是log_block_convert_lsn_to_no();接下來兩個字節(jié)表示該block中已經(jīng)有多少個字節(jié)被使用;再后邊兩個字節(jié)表示該block中作為一個新的MTR開始log record的偏移量,由于一個block中可以包含多個MTR記錄的log,所以需要有記錄表示此偏移量。再然后四個字節(jié)表示該block的checkpoint number。block trailer占用四個字節(jié),表示此log block計算出的checksum值,用于正確性校驗,MySQL5.6提供了若干種計算checksum的算法,這里不再贅述。我們可以結(jié)合代碼中給出的注釋,再了解下header和trailer的各個字段的含義。

580 /* Offsets of a log block header */581 #define LOG_BLOCK_HDR_NO0 /* block number which must be > 0 and582 is allowed to wrap around at 2G; the583 highest bit is set to 1 if this is the584 first log block in a log flush write585 segment */586 #define LOG_BLOCK_FLUSH_BIT_MASK 0x80000000UL587 /* mask used to get the highest bit in588 the preceding field */589 #define LOG_BLOCK_HDR_DATA_LEN4 /* number of bytes of log written to590 this block */591 #define LOG_BLOCK_FIRST_REC_GROUP 6 /* offset of the first start of an592 mtr log record group in this log block,593 0 if none; if the value is the same594 as LOG_BLOCK_HDR_DATA_LEN, it means595 that the first rec group has not yet596 been catenated to this log block, but597 if it will, it will start at this598 offset; an archive recovery can599 start parsing the log records starting600 from this offset in this log block,601 if value not 0 */602 #define LOG_BLOCK_CHECKPOINT_NO 8 /* 4 lower bytes of the value of603 log_sys->next_checkpoint_no when the604 log block was last written to: if the605 block has not yet been written full,606 this value is only updated before a607 log buffer flush */608 #define LOG_BLOCK_HDR_SIZE12/* size of the log block header in609 bytes */610611 /* Offsets of a log block trailer from the end of the block */612 #define LOG_BLOCK_CHECKSUM4 /* 4 byte checksum of the log block613 contents; in InnoDB versions614 < 3.23.52 this did not contain the615 checksum but the same value as616 .._HDR_NO */617 #define LOG_BLOCK_TRL_SIZE4 /* trailer size in bytes */
Log 記錄生成

在介紹了log file和log block的結(jié)構(gòu)后,需要描述log record在InnoDB內(nèi)部是如何生成的,其“生命周期”是如何在內(nèi)存中一步步流轉(zhuǎn)并最終寫入磁盤中的。這里涉及到兩塊內(nèi)存緩沖,涉及到mtr/log_sys等內(nèi)部結(jié)構(gòu),后續(xù)會一一介紹。

首先介紹下log_sys。log_sys是InnoDB在內(nèi)存中保存的一個全局的結(jié)構(gòu)體(struct名為log_t,global object名為log_sys),其維護了一塊全局內(nèi)存區(qū)域叫做log buffer(log_sys->buf),同時維護有若干lsn值等信息表示logging進行的狀態(tài)。其在log_init函數(shù)中對所有的內(nèi)部區(qū)域進行分配并對各個變量進行初始化。

log_t的結(jié)構(gòu)體很大,這里不再粘出來,可以自行看"storage/innobase/include/log0log.h: struct log_t"。下邊會對其中比較重要的字段值加以說明:

log_sys->lsn接下來將要生成的log record使用此lsn的值

log_sys->flushed_do_disk_lsn

redo log file已經(jīng)被刷新到此lsn。比該lsn值小的日志記錄已經(jīng)被安全的記錄在磁盤上

log_sys->write_lsn

當前正在執(zhí)行的寫操作使用的臨界lsn值;

log_sys->current_flush_lsn

當前正在執(zhí)行的write + flush操作使用的臨界lsn值,一般和log_sys->write_lsn相等;
log_sys->buf

內(nèi)存中全局的log buffer,和每個mtr自己的buffer有所區(qū)別;

log_sys->buf_size

log_sys->buf的size

log_sys->buf_free

寫入buffer的起始偏移量

log_sys->buf_next_to_write

buffer中還未寫到log file的起始偏移量。下次執(zhí)行write+flush操作時,將會從此偏移量開始

log_sys->max_buf_free

確定flush操作執(zhí)行的時間點,當log_sys->buf_free比此值大時需要執(zhí)行flush操作,具體看log_check_margins函數(shù)

lsn是聯(lián)系dirty page,redo log record和redo log file的紐帶。在每個redo log record被拷貝到內(nèi)存的log buffer時會產(chǎn)生一個相關(guān)聯(lián)的lsn,而每個頁面修改時會產(chǎn)生一個log record,從而每個數(shù)據(jù)庫的page也會有一個相關(guān)聯(lián)的lsn,這個lsn記錄在每個page的header字段中。為了保證WAL(Write-Ahead-Logging)要求的邏輯,dirty page要求其關(guān)聯(lián)lsn的log record已經(jīng)被寫入log file才允許執(zhí)行flush操作。

接下來介紹mtr。mtr是mini-transactions的縮寫。其在代碼中對應(yīng)的結(jié)構(gòu)體是mtr_t,內(nèi)部有一個局部buffer,會將一組log record集中起來,批量寫入log buffer。mtr_t的結(jié)構(gòu)體如下所示:

376 /* Mini-transaction handle and buffer */377 struct mtr_t{378 #ifdef UNIV_DEBUG379 ulint state;/*!< MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */380 #endif381 dyn_array_t memo; /*!< memo stack for locks etc. */382 dyn_array_t log;/*!< mini-transaction log */383 unsignedinside_ibuf:1;384 /*!< TRUE if inside ibuf changes */385 unsignedmodifications:1;386 /*!< TRUE if the mini-transaction387 modified buffer pool pages */388 unsignedmade_dirty:1;389 /*!< TRUE if mtr has made at least390 one buffer pool page dirty */391 ulint n_log_recs;392 /* count of how many page initial log records393 have been written to the mtr log */394 ulint n_freed_pages;395 /* number of pages that have been freed in396 this mini-transaction */397 ulint log_mode; /* specifies which operations should be398 logged; default value MTR_LOG_ALL */399 lsn_t start_lsn;/* start lsn of the possible log entry for400 this mtr */401 lsn_t end_lsn;/* end lsn of the possible log entry for402 this mtr */403 #ifdef UNIV_DEBUG404 ulint magic_n;405 #endif /* UNIV_DEBUG */406 };

mtr_t::log --作為mtr的局部緩存,記錄log record;

mtr_t::memo --包含了一組由此mtr涉及的操作造成的臟頁列表,其會在mtr_commit執(zhí)行后添加到flush list(參見mtr_memo_pop_all()函數(shù));

mtr的一個典型應(yīng)用場景如下:

1. 創(chuàng)建一個mtr_t類型的對象;

2. 執(zhí)行mtr_start函數(shù),此函數(shù)將會初始化mtr_t的字段,包括local buffer;

3. 在對內(nèi)存bp中的page進行修改的同時,調(diào)用mlog_write_ulint類似的函數(shù),生成redo log record,保存在local buffer中;

4. 執(zhí)行mtr_commit函數(shù),此函數(shù)將會將local buffer中的redo log拷貝到全局的log_sys->buffer,同時將臟頁添加到flush list,供后續(xù)執(zhí)行flush操作時使用;

mtr_commit函數(shù)調(diào)用mtr_log_reserve_and_write,進而調(diào)用log_write_low執(zhí)行上述的拷貝操作。如果需要,此函數(shù)將會在log_sys->buf上創(chuàng)建一個新的log block,填充header、tailer以及計算checksum。

我們知道,為了保證數(shù)據(jù)庫ACID特性中的原子性和持久性,理論上,在事務(wù)提交時,redo log應(yīng)已經(jīng)安全原子的寫到磁盤文件之中。回到MySQL,文件內(nèi)存中的log_sys->buffer何時以及如何寫入磁盤中的redo log file與innodb_flush_log_at_trx_commit的設(shè)置密切相關(guān)。無論對于DBA還是MySQL的使用者對這個參數(shù)都已經(jīng)相當熟悉,這里直接舉例不同取值時log子系統(tǒng)是如何操作的。

innodb_flush_log_at_trx_commit=1/2。此時每次事務(wù)提交時都會寫redo log,不同的是1對應(yīng)write+flush,2只write,而由指定線程周期性的執(zhí)行flush操作(周期多為1s)。執(zhí)行write操作的函數(shù)是log_group_write_buf,其由log_write_up_to函數(shù)調(diào)用。一個典型的調(diào)用棧如下:

(trx_commit_in_memory()/trx_commit_complete_for_mysql()/trx_prepare() e.t.c)->trx_flush_log_if_needed()->trx_flush_log_if_needed_low()->log_write_up_to()->log_group_write_buf().

log_group_write_buf會再調(diào)用innodb封裝的底層IO系統(tǒng),其實現(xiàn)很復(fù)雜,這里不再展開。

innodb_flush_log_at_trx_commit=0時,每次事務(wù)commit不會再調(diào)用寫redo log的函數(shù),其寫入邏輯都由master_thread完成,典型的調(diào)用棧如下:

srv_master_thread()->(srv_master_do_active_tasks() / srv_master_do_idle_tasks() / srv_master_do_shutdown_tasks())->srv_sync_log_buffer_in_background()->log_buffer_sync_in_background()->log_write_up_to()->... .

除此參數(shù)的影響之外,還有一些場景下要求刷新redo log文件。這里舉幾個例子:

1)為了保證write ahead logging(WAL),在刷新臟頁前要求其對應(yīng)的redo log已經(jīng)寫到磁盤,因此需要調(diào)用log_write_up_to函數(shù);

2)為了循環(huán)利用log file,在log file空間不足時需要執(zhí)行checkpoint(同步或異步),此時會通過調(diào)用log_checkpoint執(zhí)行日志刷新操作。checkpoint會極大的影響數(shù)據(jù)庫的性能,這也是log file不能設(shè)置的太小的主要原因;

3)在執(zhí)行一些管理命令時要求刷新redo log文件,比如關(guān)閉數(shù)據(jù)庫;

這里再簡要總結(jié)一下一個log record的“生命周期”:

1. redo log record首先由mtr生成并保存在mtr的local buffer中。這里保存的redo log record需要記錄數(shù)據(jù)庫恢復(fù)階段所需的所有信息,并且要求恢復(fù)操作是冪等的;

2. 當mtr_commit被調(diào)用后,redo log record被記錄在全局內(nèi)存的log buffer之中;

3. 根據(jù)需要(需要額外的空間?事務(wù)commit?),redo log buffer將會write(+flush)到磁盤上的redo log文件中,此時redo log已經(jīng)被安全的保存起來;

4. mtr_commit執(zhí)行時會給每個log record生成一個lsn,此lsn確定了其在log file中的位置;

5. lsn同時是聯(lián)系redo log和dirty page的紐帶,WAL要求redo log在刷臟前寫入磁盤,同時,如果lsn相關(guān)聯(lián)的頁面都已經(jīng)寫入了磁盤,那么磁盤上redo log file中對應(yīng)的log record空間可以被循環(huán)利用;

6. 數(shù)據(jù)庫恢復(fù)階段,使用被持久化的redo log來恢復(fù)數(shù)據(jù)庫;

接下來介紹redo log在數(shù)據(jù)庫恢復(fù)階段所起的重要作用。

Log Recovery

InnoDB的recovery的函數(shù)入口是innobase_start_or_create_for_mysql,其在mysql啟動時由innobase_init函數(shù)調(diào)用。我們接下來看下源碼,在此函數(shù)內(nèi)可以看到如下兩個函數(shù)調(diào)用:

1. recv_recovery_from_checkpoint_start

2. recv_recovery_from_checkpoint_finish

代碼注釋中特意強調(diào),在任何情況下,數(shù)據(jù)庫啟動時都會嘗試執(zhí)行recovery操作,這是作為函數(shù)啟動時正常代碼路徑的一部分。

主要恢復(fù)工作在第一個函數(shù)內(nèi)完成,第二個函數(shù)做掃尾清理工作。這里,直接看函數(shù)的注釋可以清楚函數(shù)的具體工作是什么。

146 /** Wrapper for recv_recovery_from_checkpoint_start_func().147 Recovers from a checkpoint. When this function returns, the database is able148 to start processing of new user transactions, but the function149 recv_recovery_from_checkpoint_finish should be called later to complete150 the recovery and free the resources used in it.151 @param type in: LOG_CHECKPOINT or LOG_ARCHIVE152 @param limin: recover up to this log sequence number if possible153 @param minin: minimum flushed log sequence number from data files154 @param maxin: maximum flushed log sequence number from data files155 @return error code or DB_SUCCESS */156 # define recv_recovery_from_checkpoint_start(type,lim,min,max)/157 recv_recovery_from_checkpoint_start_func(type,lim,min,max)

與log_t結(jié)構(gòu)體相對應(yīng),恢復(fù)階段也有一個結(jié)構(gòu)體,叫做recv_sys_t,這個結(jié)構(gòu)體在recv_recovery_from_checkpoint_start函數(shù)中通過recv_sys_create和recv_sys_init兩個函數(shù)初始化。recv_sys_t中同樣有幾個和lsn相關(guān)的字段,這里做下介紹。

recv_sys->limit_lsn

恢復(fù)應(yīng)該執(zhí)行到的最大的LSN值,這里賦值為LSN_MAX(uint64_t的最大值)

recv_sys->parse_start_lsn

恢復(fù)解析日志階段所使用的最起始的LSN值,這里等于最后一次執(zhí)行checkpoint對應(yīng)的LSN值

recv_sys->scanned_lsn

當前掃描到的LSN值

recv_sys->recovered_lsn

當前恢復(fù)到的LSN值,此值小于等于recv_sys->scanned_lsn
parse_start_lsn值是recovery的起點,其通過recv_find_max_checkpoint函數(shù)獲取,讀取的就是log文件LOG_CHECKPOINT_1/LOG_CHECKPOINT_2字段的值。

在獲取start_lsn后,recv_recovery_from_checkpoint_start函數(shù)調(diào)用recv_group_scan_log_recs函數(shù)讀取及解析log records。

我們重點看下recv_group_scan_log_recs函數(shù):

2908 /*******************************************************//**2909 Scans log from a buffer and stores new log data to the parsing buffer. Parses2910 and hashes the log records if new data found. */2911 static2912 void2913 recv_group_scan_log_recs(2914 /*=====================*/2915 log_group_t*group,/*!< in: log group */2916 lsn_t*contiguous_lsn, /*!< in/out: it is known that all log2917 groups contain contiguous log data up2918 to this lsn */2919 lsn_t*group_scanned_lsn)/*!< out: scanning succeeded up to2920 this lsn */2930 while (!finished) {2931 end_lsn = start_lsn + RECV_SCAN_SIZE;29322933 log_group_read_log_seg(LOG_RECOVER, log_sys->buf,2934group, start_lsn, end_lsn);29352936 finished = recv_scan_log_recs(2937 (buf_pool_get_n_pages()2938 - (recv_n_pool_free_frames * srv_buf_pool_instances))2939 * UNIV_PAGE_SIZE,2940 TRUE, log_sys->buf, RECV_SCAN_SIZE,2941 start_lsn, contiguous_lsn, group_scanned_lsn);2942 start_lsn = end_lsn;2943 }

此函數(shù)內(nèi)部是一個while循環(huán)。log_group_read_log_seg函數(shù)首先將log record讀取到一個內(nèi)存緩沖區(qū)中(這里是log_sys->buf),接著調(diào)用recv_scan_log_recs函數(shù)用來解析這些log record。解析過程會計算log block的checksum以及block no和lsn是否對應(yīng)。解析過程完成后,解析結(jié)果會存入recv_sys->addr_hash維護的hash表中。這個hash表的key是通過space id和page number計算得到,value是一組應(yīng)用到指定頁面的經(jīng)過解析后的log record,這里不再展開。

上述步驟完成后,recv_apply_hashed_log_recs函數(shù)可能會在recv_group_scan_log_recs或recv_recovery_from_checkpoint_start函數(shù)中調(diào)用,此函數(shù)將addr_hash中的log應(yīng)用到特定的page上。此函數(shù)會調(diào)用recv_recover_page函數(shù)做真正的page recovery操作,此時會判斷頁面的lsn要比log record的lsn小。

105 /** Wrapper for recv_recover_page_func().106 Applies the hashed log records to the page, if the page lsn is less than the107 lsn of a log record. This can be called when a buffer page has just been108 read in, or also for a page already in the buffer pool.109 @param jriin: TRUE if just read in (the i/o handler calls this for110 a freshly read page)111 @param blockin/out: the buffer block112 */113 # define recv_recover_page(jri, block)recv_recover_page_func(jri, block)

如上就是整個頁面的恢復(fù)流程。

附一個問題環(huán)節(jié),后續(xù)會將redo log相關(guān)的問題記錄在這里。

1. Q: Log_file, Log_block, Log_record的關(guān)系?
A: Log_file由一組log block組成,每個log block都是固定大小的。log block中除了header/tailer以外的字節(jié)都是記錄的log record
2. Q: 是不是每一次的Commit,產(chǎn)生的應(yīng)該是一個Log_block ?
A: 這個不一定的。寫入log_block由mtr_commit確定,而不是事務(wù)提交確定??磍og record大小,如果大小不需要跨log block,就會繼續(xù)在當前的log block中寫 。
3. Q: Log_record的結(jié)構(gòu)又是怎么樣的呢?
A: 這個結(jié)構(gòu)很多,也沒有細研究,具體看后邊登博圖中的簡要介紹吧;
4. Q: 每個Block應(yīng)該有下一個Block的偏移嗎,還是順序即可,還是記錄下一個的Block_number
A: block都是固定大小的,順序?qū)懙?
5. Q: 那如何知道這個Block是不是完整的,是不是依賴下一個Block呢?
A: block開始有2個字節(jié)記錄 此block中第一個mtr開始的位置,如果這個值是0,證明還是上一個block的同一個mtr。
6. Q: 一個事務(wù)是不是需要多個mtr_commit
A: 是的。mtr的m == mini;
7. Q: 這些Log_block是不是在Commit的時候一起刷到當中?
A: mtr_commit時會寫入log buffer,具體什么時候?qū)懙絣og file就不一定了
8. Q: 那LSN是如何寫的呢?
A: lsn就是相當于在log file中的位置,那么在寫入log buffer時就會確定這個lsn的大小了 。當前只有一個log buffer,在log buffer中的位置和在log file中的位置是一致的
9. Q: 那我Commit的時候做什么事情呢?
A: 可能寫log 、也可能不寫,由innodb_flush_log_at_trx_commit這個參數(shù)決定啊
10. Q: 這兩個值是干嘛用的: LOG_CHECKPOINT_1/LOG_CHECKPOINT_2
A: 這兩個可以理解為log file頭信息的一部分(占用文件頭第二和第四個block),每次執(zhí)行checkpoint都需要更新這兩個字段,后續(xù)恢復(fù)時,每個頁面對應(yīng)lsn中比這個checkpoint值小的,認為是已經(jīng)寫入了,不需要再恢復(fù)

文章最后,將網(wǎng)易杭研院何登成博士-登博博客上的一個log block的結(jié)構(gòu)圖放在這,再畫圖也不會比登博這張圖畫的更清晰了,版權(quán)屬于登博。

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

MySQLredolog及recover過程淺析

MySQLredolog及recover過程淺析:寫在前面:作者水平有限,歡迎不吝賜教,一切以最新源碼為準。InnoDB redo log首先介紹下Innodb redo log是什么,為什么需要記錄redo log,以及redo log的作用都有哪些。這些作為常識,只是為了本文完整。InnoDB有buffer pool(簡稱bp)。b
推薦度:
標簽: 記錄 流程 博客
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top