innodb 01 redo 日誌詳解

2021-10-14 10:13:14 字數 3542 閱讀 4494

1、二進位制日誌server層產生,redo是innodb層產生。並且binlog先於redolog被記錄

2、binlog記錄操作的方法是邏輯性的語句,基於行格式。redolog是innodb層產生的日誌,記錄資料庫每個頁的修改。

3、binlog是事務提交的時候,一次性寫入,redolog是資料準備修改的時候寫入redobuffer,然後才對快取中資料操作。並且保證,事務提交時:redobuffer沖刷到磁碟

4、binlog是一次性寫入,所以有順序。redolog是物理頁的修改,所以可能同乙個事務多次記錄,並且redolog是併發寫入的,不同事務之間的不同版本會穿插到redolog中。

5、事務日誌記錄的是物理頁的情況,它具有冪等性,因此記錄日誌的方式極其簡練。而二進位制日誌記錄的是所有影響資料的操作,記錄的內容較多。

redo包含兩個部分:記憶體中的日誌緩衝redobuffer + 磁碟上的日誌檔案redolog.事務提交的時候,必須把該事務的所有日誌都寫入到磁碟的redolog中。

redobuffer 在使用者區,先複製到核心取,然後fsync刷盤。

關於為何要經過核心緩衝區的理解:使用o_direct表示寫磁碟繞過os buffer,但是這樣會降低順序寫的效率(寫abcde,將發起五次fsync)。

double write的思路很簡單:

a. 在覆蓋磁碟上的資料前,先將page的內容寫入到磁碟上的其他地方(innodb儲存引擎中的doublewrite buffer,這裡的buffer不是記憶體空間,是持久儲存上的空間).

b. 然後再將page的內容覆蓋到磁碟上原來的資料。

如果在a步驟時系統故障,原來的資料沒有被覆蓋,還是完整的。

如果在b步驟時系統故障,原來的資料不完整了,但是新資料已經被完整的寫入了doublewrite buffer. 因此系統恢復時就可以用doublewrite buffer中的新page來覆蓋這個不完整的page。

doublewrite由兩部分組成,一部分是記憶體中的 doublewrite buffer,大小為2mb,另部分是物理磁碟上共享表空間中連續的128個頁,

即2個區( extent),大小同樣為2mb。在對緩衝池的髒頁進行重新整理時,並不直接寫磁碟,而是會通過 memcpy函式將髒頁先複製到記憶體中的

doublewrite buffer,之後通過 doublewrite buffer再分兩次,每次1mb順序地寫入共享表空間的物理磁碟上,然後馬上呼叫 fsync函式,

同步磁碟,避免緩衝寫帶來的問題。在這個過程中,因為 doublewrite頁是連續的,因此這個過程是順序寫的,開銷並不是很大。

在完成 doublewrite頁的寫入後,再將 doublewrite buffer中的頁寫入各個表空間檔案中,此時的寫入則是離散的。

innodb_flush_log_at_trx_commit引數決定:

0:提交事務的時候,並不把redolog重新整理到磁碟上去。而是等待主線程每秒的重新整理

1:提交事務的時候,同時刷盤redolog。

2:表示將事務非同步寫到磁碟,即寫到檔案系統的快取中去。

redo buffer 或者redo file 由很多日誌塊組成。

block = 塊頭(12位元組) + 塊(492) + 塊尾(8位元組)

塊頭 = 日誌塊在buffer中的id + 日誌塊已寫日誌的大小 + 日誌塊中第乙個日誌的位置 +寫入檢查點資訊的位置、

塊尾 = 日誌塊在buffer中的id

乙個log group由多個完全相同的redolog file 組成。log group是邏輯的。redo log file是物理的。

innodb_log_files_group 引數決定 redo log file 的數量

innodb_log_group_home_dir 引數決定 redo log file的位置

每個redo log file前2kb都是預留空間。第乙個redo log file記錄了group的資訊。其他redo log file的這2kb為空。

在redo block 中,中間的塊部分是log body(492位元組)

log body = 日誌型別(1位元組)+ 表空間id(4位元組) + 頁的偏移量 + 資料

其中資料部分,插入和刪除格式是不一樣的。

1.發出commit動作時。已經說明過,commit發出後是否刷日誌由變數 innodb_flush_log_at_trx_commit 控制。

2.每秒刷一次。這個刷日誌的頻率由變數 innodb_flush_log_at_timeout 值決定,預設是1秒。要注意,這個刷日誌頻率和commit動作無關。

3.當log buffer中已經使用的記憶體超過一半時。

4.當有checkpoint時,checkpoint在一定程度上代表了刷到磁碟時日誌所處的lsn位置。

在innodb中,資料刷盤的規則只有乙個:checkpoint。但是觸發checkpoint的情況卻有幾種。

兩種觸發:

sharp(銳利的; 急劇的) checkpoint:在資料庫關閉的時候,將所有髒頁刷盤

fuzzy(毛茸茸的) checkpoint:

master :執行緒每秒或者每10秒,進行重新整理。

flush_lru_list :保證lru中有100個空閒(數量可調整)。page clearner thread 重新整理

async/sync flush:重做日誌檔案不可用的時候進行的重新整理(75%—>非同步、90%—>同步)。(redo log是迴圈使用的,避免覆蓋,見上文)

dirty page too much:髒頁太多了,導致緩衝區沒有足夠可用的頁。mysql 5.6預設的值為75,即當髒頁佔緩衝池的百分之75後,就強制刷一部分髒頁到磁碟。

由變數innodb_fast_shutdown=控制,預設值為1,即停止時只做一部分purge,忽略大多數flush操作(但至少會刷日誌),在下次啟動的時候再flush剩餘的內容,實現fast shutdown。

log sequence number就是當前的redo log(in buffer)中的lsn;

log flushed up to是刷到redo log file on disk中的lsn;

pages flushed up to是已經刷到磁碟資料頁上的lsn;

last checkpoint at是上一次檢查點所在位置的lsn。

但是其實:記憶體資料頁也有lsn。所以

記憶體資料頁的lsn >= redo log(buffer)的lsn >= redo log(disk)的lsn >= 已經刷到磁碟資料頁上的ls >= 上一次檢查點所在位置的lsn(上一次checkpoint)

1、重啟innodb時,checkpoint表示已經完整刷到磁碟上data page上的lsn,因此恢復時僅需要恢復從checkpoint開始的日誌部分

2、還有一種情況,在宕機前正處於checkpoint的刷盤過程,且資料頁的刷盤進度超過了日誌頁的刷盤進度。這時候一宕機,資料頁中記錄的lsn就會大於日誌頁中的lsn,在重啟的恢復過程中會檢查到這一情況,這時超出日誌進度的部分將不會重做,因為這本身就表示已經做過的事情,無需再重做。

3、另外,事務日誌具有冪等性,所以多次操作得到同一結果的行為在日誌中只記錄一次。而二進位制日誌不具有冪等性,多次操作會全部記錄下來,在恢復的時候會多次執行二進位制日誌中的記錄,速度就慢得多。

innodb引擎redo檔案維護

如果要對innodb的redo日誌檔案的大小與個數進行調整可以採用如下步驟 1 關閉mysql mysqladmin h127.0.0.1 p3306 uroot p shutdown 2 修改配置檔案中的innodb log file size innodb log files in group ...

InnoDB儲存引擎redo和undo log

1 undo log undo log 是為了實現事務的原子性,在mysql資料庫innodb儲存引擎中,還用undo log來實現多版本併發控制 簡稱 mvcc 事務的原子性 atomicity 事務中的所有操作,要麼全部完成,要麼不做任何操作,不能只做部分操作。如果在執行的過程中發生了錯誤,要回...

SpringClou day01學習錯誤日記

1.ieda中使用註解 slf4j為什麼找不到變數log?解決 安裝lombok外掛程式後,清快取重啟依然不行,最後新建了乙個springboot專案,將slf4j的版本號修改為父工程的依賴版本號 因為springboot父工程的版本號是相容性最好的 2.乙個小錯誤,寫的paymentservice...