中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

InnoDB Redo Log的設計原理以及源碼是怎樣的

發布時間:2021-10-08 17:23:31 來源:億速云 閱讀:288 作者:柒染 欄目:MySQL數據庫

本篇文章為大家展示了InnoDB Redo Log的設計原理以及源碼是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

這篇文章主要學習 InnoDB Redo Log 的流程。Redo Log 是 InnoDB 實現數據一致性和持久化存儲的關鍵,主要從設計原理和部分源碼實現出發,對其中的知識點進行歸納總結。

Redo Log Buffer & Redo Log File

前面兩篇文章已經描述過,InnoDB 使用 Redo Log 來保證數據的一致性和可持久性,它采用 WAL 機制,即先寫日志再寫數據。具體來說,InnoDB 進行寫操作時,先將數據操作記錄在 log buffer 中,然后將 log buffer 中的數據刷到磁盤 log file 中,后續數據再落到數據 ibd 文件這一步驟由 checkpoint 來保證。其數據流如下圖所示。

InnoDB Redo Log的設計原理以及源碼是怎樣的

另外有一個細節值得注意:雖然對于一個事務來講,還需要再成功寫入 binlog 文件,才能認為事務完成,但單從存儲層的視角來看,在某個時刻,數據文件加上 Redo Log File 就是此時刻數據庫的一個完整快照,像 Xtrabackup 這類的物理備份工具,就是通過拷貝數據文件和 Redo Log File 來進行全量備份的。

Redo Log 元數據及其初始化流程

InnoDB 使用 log_sys 這個對象來管理 Redo Log Buffer,其結構體為 log_t,它在源碼中的定義(部分數據被折疊)如下。

InnoDB Redo Log的設計原理以及源碼是怎樣的log_t 結構體定義 (/innobase/include/log0log.h)

log_sys 主要包括以下元數據信息:

InnoDB Redo Log的設計原理以及源碼是怎樣的

在 log_sys 元數據信息中有一個非常重要的概念 — LSN。

LSN 即日志序列號( Log Sequence Number ),它代表 Redo Log 的序號,它是單調遞增的,每寫入一個 Redo Log 時,LSN 就會遞增該 Redo Log 寫入的字節數,因此,LSN 就像是時間點一樣,記錄了每個 Redo Log 產生的時序,并且和 Redo Log 一一對應,我們后面會具體描述 LSN 和 Redo Log 之間是如何轉換的。

log_sys 對象是在 InnoDB 啟動時,由 log_init() 函數負責初始化,主要是對元數據信息進行賦值操作。其部分代碼實現如下:

InnoDB Redo Log的設計原理以及源碼是怎樣的

log_init()函數實現 (/innobase/log/log0log.cc)

log_init() 函數另一個重要的步驟是對 log 對象 log_block 進行初始化。log_block 是 Redo Log 的最小數據管理單元,其大小為 512 Bytes。log_block 并沒有單獨的結構體來進行管理,其元數據信息存在于自身的前 12 個字節中,這部分信息稱為 log_block_header,另外,log_block 還包括 8 個字節的 log_block_tail 信息,因此,每個 log_block 實際可存儲空間為 492 Bytes。log_sys 和 log_block 的結構信息如下圖。

InnoDB Redo Log的設計原理以及源碼是怎樣的

正如上圖所標注的信息,log_block_header 包含如下信息:

InnoDB Redo Log的設計原理以及源碼是怎樣的

log_block_init() 函數進行的操作如下:

InnoDB Redo Log的設計原理以及源碼是怎樣的

log_block_init()函數實現 (/innobase/include/log0log.ic)

首先,通過該 log_block 的 lsn 值計算出 log_block 的編號,即 log_block_hdr_no,前面已經提到過,log_block 沒有其他的數據結構進行組織,因此該編號唯一標識了 log_block 在 log buffer 中的位置。lsn 到 log_block_hdr_no 的轉換由函數 log_block_convert_lsn_to_no() 實現,實現邏輯為:

UNIV_INLINE
ulint
log_block_convert_lsn_to_no(
/*========================*/
    lsn_t    lsn)    /*!< in: lsn of a byte within the block */
{
    return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & 0x3FFFFFFFUL) + 1);
}

這個邏輯還是比較簡單,因為日志都是按 log_block_size(512 Bytes) 存儲的,并且 lsn 單調增加,因此 lsn 其實是 log_block_size 的倍數再加上當前偏移量。

計算出log_block編號后,log_block_set_hdr_no() 函數將該編號記錄在 log_block 的前 4 個字節中。然后 log_block_set_data_len() 函數設置該 log_block 默認已使用的空間 LOG_BLOCK_HDR_SIZE,即 12 Bytes。

在實際記錄 log 的過程中,一次寫 log 的大小可能大于 512 Bytes,即連續占用多個 log_block,所以 log_block 中可能包含多個 log 的內容,因此用 log_block_first_rec_group 記錄了 log_block 中第一個日志的偏移量。該變量的值也會被設置成 LOG_BLOCK_HDR_SIZE 的大小。

上面講到的 log_init() 的整個流程是在 InnoDB 存儲引擎的初始化過程中實現的。學習一個復雜系統,從它的初始化流程入手會比較有幫助,就像學習一個文件系統,從 xxxfs_init() 入手,你可以很快的了解 super_block 是如何初始化的,inodes 是如何組織的,學習 InnoDB 也是同樣的道理。InnoDB 的初始化流程是由 innobase_start_or_create_for_mysql() 這個函數來實現的,它負責初始化 InnoDB 所需要的各種元數據信息,如 Buffer Pool 結構、LRU 鏈表、各種文件數據結構、日志數據結構、鎖信息、設置 InnoDB 的各種參數變量等。除了我們講到的 log_init() 流程,還包括 fil_init(), buf_pool_init(), fsp_init(), buf_flush_page_cleaner_init() 等。例如 buf_pool_init() 流程所做的工作初始化 Buffer Pool Instance 對象的結構體 buf_pool_t,包括對 buffer_pool_chunks 的初始化,多個 LRU 鏈表和指針變量的初始化等。

CheckPoint & LSN

前面已經提到,Buffer Pool 中的數據落盤操作,是由 checkpoint 來執行的。checkpoint 負責將內存數據同步到磁盤數據文件中,以確保數據的一致性。checkpoint 執行的情況決定了數據庫在進行災難恢復時所需要的時間,在數據庫進行災難恢復時,只需要恢復從 checkpoint 到最近的 Redo Log 這段日志中的數據,就可以恢復到宕機之前的狀態。LSN 記錄了 Redo Log 產生的時序,日志寫到 log buffer 以及 log buffer 數據落盤到 log file,都是根據 LSN 來往前推進的。而 checkpoint 也是根據 LSN 的時序來進行刷盤操作的。在 MySQL 中執行 show engine innodb status 可以看到:

InnoDB Redo Log的設計原理以及源碼是怎樣的

由于系統寫入量較少,當前系統產生的 lsn 和已經刷到 Redo Log File 的 lsn 值是一致的。而 Buffer Pool 中數據頁刷盤的進度和執行 checkpoint 的進度都較為落后。

Group Commit

InnoDB 允許多個事務產生的 Redo Log 一起提交,來減少磁盤 I/O。首先我們再來闡述一下 Redo Log 和 Binlog 的區別。Redo Log 是 InnoDB 存儲層特有的日志,記錄的是物理頁數據的變更,而 Binlog 是 MySQL 都有的,記錄的邏輯日志。Binlog 只有事務提交時進行一次寫入,而 Redo Log 的寫入時機則有多種。首先,在事務提交時,若設置了參數 innodb_flush_log_at_trx_commit 為 1,則會進行刷盤操作;其次,當 Redo Log Buffer 空間不足時,系統也會強制進行刷盤操作;另外后臺線程也會每秒進行一次刷盤操作。

如果是在多并發事務的情況下,某個事務在事務過程中產生的 log (已寫入到 log buffer 中),可能會被其他事務的提交帶到 log file 中,也可能被后臺線程進行刷盤,這樣就達到了 Group Commit 的效果。同時也可以看到,一個事務產生的 log 并不是在事務提交時一次寫到 log file 的,而是在事務過程中不斷寫入到 log file 的。

上述內容就是InnoDB Redo Log的設計原理以及源碼是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乌拉特前旗| 长春市| 横峰县| 绍兴县| 芜湖市| 九江市| 民乐县| 武冈市| 芦山县| 大港区| 盖州市| 华蓥市| 图木舒克市| 宜昌市| 祁东县| 瓮安县| 西充县| 贺州市| 纳雍县| 崇左市| 冷水江市| 淮滨县| 巨野县| 高州市| 巴彦县| 准格尔旗| 农安县| 叶城县| 西昌市| 东明县| 呼图壁县| 安多县| 尚志市| 三亚市| 公安县| 乌什县| 保康县| 冕宁县| 高平市| 上栗县| 大悟县|