天天看點

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

MySql系列整體欄目

内容 連結位址
【一】深入了解mysql索引本質 https://blog.csdn.net/zhenghuishengq/article/details/121027025
【二】深入了解mysql索引優化以及explain關鍵字 https://blog.csdn.net/zhenghuishengq/article/details/124552080
【三】深入了解mysql的索引分類,覆寫索引(失效),回表,MRR https://blog.csdn.net/zhenghuishengq/article/details/128273593
【四】深入了解mysql事務本質 https://blog.csdn.net/zhenghuishengq/article/details/127753772
【五】深入了解mvcc機制 https://blog.csdn.net/zhenghuishengq/article/details/127889365
【六】深入了解mysql的核心查詢成本計算 https://blog.csdn.net/zhenghuishengq/article/details/128820477
【七】深入了解mysql性能優化以及解決慢查詢問題 https://blog.csdn.net/zhenghuishengq/article/details/128854433
【八】深入了解innodb和buffer pool底層結構和原理 https://blog.csdn.net/zhenghuishengq/article/details/128993871
【九】深入了解mysql執行的底層機制 https://blog.csdn.net/zhenghuishengq/article/details/128100377
【十】深入了解redolog,undolog和binlog的底層原理 https://blog.csdn.net/zhenghuishengq/article/details/129183623
【十一】深入了解mysql叢集的高可用機制 https://blog.csdn.net/zhenghuishengq/article/details/126239652
【彩蛋篇】深入了解順序io和随機io https://blog.csdn.net/zhenghuishengq/article/details/129080088

深入了解redolog,undolog和binlog的底層原理和關系

  • 一, 深入了解Redolog日志底層原理
    • 1,innodb引擎底層事務原理
      • 1.1,WAL
    • 2,redolog日志檔案
      • 2.1,為什麼要redolog日志檔案
      • 2.2,redolog的内部結構
      • 2.3,redolog的刷盤時機
      • 2.4,Log Sequence Number
      • 2.5,innodb_flush_log_at_trx_commit
    • 3,undolog日志
      • 3.1,undolog復原的方式
      • 3.2,undolog事務id形成機制
      • 3.3,插入操作
      • 3.4,删除操作
      • 3.5,更新操作
        • 3.5.1,不更新主鍵
        • 3.5.2,更新主鍵
    • 4,事務的整體執行流程
    • 5,redolog和binlog的關系
      • 5.1,為什麼用redolog恢複資料而不用binlog
      • 5.2,binlog和redolog如何保證資料的一緻性

一, 深入了解Redolog日志底層原理

再看本篇文章之前,可以結合【9】深入了解mysql執行的底層機制 這篇文章來了解mysql内部執行sql的過程。

1,innodb引擎底層事務原理

事務的四大特性主要是是acid,分别是原子性、一緻性、隔離性和持久性。其原子性是 通過這個undolog 來保證的,持久性是 通過redolog 來實作的,隔離性是通過事務的 讀寫鎖+mvcc機制 來實作的。在這四大特性中,一緻性C是最重要的,他是最終目的,隻有其他三個實作了,才有可能實作這個一緻性,即 一緻性是最終目的,其他三個就是實作的手段 。

1.1,WAL

在事務的具體實作的機制中,mysql是通過這個WAL(Write-ahead logging),即預寫日志的方式來實作的。

舉個基本的例子,假設一個轉錢的操作,如果A給B轉錢,此時A減了100,而在B在加100的時候,突然斷電了,那麼在資料庫重新開機的時候,就得恢複他斷電前的狀态,此時就需要一個日志來記錄他事務操作前的狀态了,通過這個日志中的記錄來恢複之前的狀态,判斷其是否需要復原操作,還是需要重做等操作。而實作這個WBL機制,主要是通過這個redolog和undolog這兩種日志的方式實作。

mysql中除了使用這種主流的WAL機制之外,還會使用一些Commit Logging丶Shadow Paging等。mysql預設使用這個WAL機制。

2,redolog日志檔案

2.1,為什麼要redolog日志檔案

依舊拿一個更新語句舉例,如下圖,redolog是發生在第4步和第5步,在資料在buffer pool中進行資料更新之後,會把具體的邏輯語句,如哪一頁哪一行要更新的字段以及更新的值是啥,先加入到redolog buffer中,随後再然後通過追加的方式持久化到磁盤上的redolog檔案中,再不考慮server層的操作,即跳過6,7步,那麼就會啟動一個背景線程進行一個落盤的操作。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

這裡假設innodb内部沒有這個redolog這個日志檔案,就是在資料更新之後直接從buffer pool将資料給落盤,如果在落盤的時候資料頁沒有發生損壞,那麼雙寫機制就觸發不了,就沒有換頁的操作,此時發生斷電,那麼還沒來的及落盤的資料就會直接丢失了,這就會影響資料的安全性和持久化。

除了斷電這個問題,還有可能因為一個小小的更新語句,就直接将整頁資料給進行落盤操作,這樣就很浪費成本;或者遇到一個sql很複雜,需要涉及的表很多,并且資料量很大,那麼就需要更改很多頁目錄的資料,如果這些頁目錄在磁盤上的分布是随機的,那麼在刷盤寫資料的時候,就會産生大量的随機io,是以也很影響内部的執行效率和浪費空間。

是以為了解決資料的安全性以及innodb的執行效率,就引入了這個redolog日志檔案,就是在落盤時先寫一份到redolog中,并且寫資料是順序寫,在redolog寫成功之後,再進行落盤操作,如果出現斷電問題,就用這個redolog這個檔案進行資料的重做。

2.2,redolog的内部結構

redolog主要是記錄了哪些資料做了什麼修改,是以這個redolog有一個通用的格式,如下圖:

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理
key value
type 就是值資料的類型,類型總共有53種
Space ID 表空間id,即修改的對應表空間的id
page Number 目前頁的頁号
data 要修改的内容

2.3,redolog的刷盤時機

在innodb的體系結構中,可以發現在左邊的記憶體結構中是有一個Log Buffer的緩沖區的,該緩沖區就是對應的redolog緩沖區,在該緩沖區中,其預設大小為16M,并且内部分成了多個小塊,每一塊的大小空間為512kb。在資料寫入這個redolog的緩沖區的時候,會從頭到尾的以追加的方式将資料寫入這些塊中,如果後面的塊快寫滿,那麼會将前面頭部的塊的資料删掉,然後再從頭到尾開始存儲資料,磁盤上面的redolog頁結構和這個一樣。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

而這個緩沖區刷盤的情況有好幾種,如下:

1,log buffer空間不足時,雖然說redolog緩沖區資料存滿會将前面的資料删除再重新存儲,但是删除之前也是要考慮資料的持久化的,innodb内部認為,當資料量達到redolog緩沖區空間的一半大小時,就需要強制的進行一次刷盤操作,進而把日志落盤到磁盤上。

2,事務送出時,在事務送出時,也是需要将緩沖區中對應的那些日志資料重新整理到磁盤的

3,背景預設線程,背景也是會啟動一個預設的線程進行一個刷盤操作的,如每一秒重新整理一次

4,伺服器手動關閉,在伺服器關閉時,也是需要将未刷盤的資料全部的進行一次刷盤操作。

2.4,Log Sequence Number

簡稱LSN,顧名思義,這個就是一個日志序列号。和undolog一樣,在執行一條更新或者插入語句的時候,就會生成一個事務id,這裡的序列号和undolog的事務id的作用是一樣的,主要是是保證資料的唯一性。該值是一個自增的序列号,初始大小為8704,後面每增加一條資料,其對應的序列号的值就會加1。即LSN的值越小,那麼其事務産生的越早。

除了這個日志之外,innodb内部還有其他的LSN用來記錄已經刷盤的事務id。可以通過具體的指令來檢視系統中各種LSN的值

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理
key value
Log sequence number 已經寫入redolog buffer的日志量(累加值)
Log flushed up to 已經寫入磁盤的redo日志量

2.5,innodb_flush_log_at_trx_commit

在資料進行刷盤的時候,資料也不是直接的從redolog緩沖區将資料直接刷到磁盤内部,而是需要調用作業系統,通過作業系統進行一個落盤的操作。在作業系統中,會有一個作業系統的緩沖區,資料會先在緩沖區中存放,然後再通過作業系統的排程将資料進行一個落盤的操作。

這個系統變量的名稱就是innodb_flush_log_at_trx_commit,可以提供給外部調用,如kafka,mysql都對這個變量進行了調用。這個變量總共有三個參數,分别是0、1、2,不同的參數代表着不同的含義:

該值為0時,表示在事務送出時不立即向磁盤中同步redo日志,這個任務是交給背景線程做的。

該值為1時,表示在事務送出時需要将redo日志同步到磁盤,可以保證事務的持久性,這個是mysql設定的系統預設值,當事務送出時,會進行一個強制刷盤的操作。

該值為2時,表示在事務送出時需要将redo日志寫到作業系統的緩沖區中,但并不需要保證将日志真正的重新整理到磁盤。如果資料還在作業系統緩存中突然斷電,那麼未落盤的資料也會丢失。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

3,undolog日志

上面主要了解redolog日志,redolog主要是為了保證這個資料的持久性,ACID中的D就是靠這個redolog來保證的。而接下來要讨論的undolog日志,undolog日志主要是為了保證資料的原子性,在mvcc那篇https://blog.csdn.net/zhenghuishengq/article/details/127889365,中也詳細的分析了這個undolog,也詳細的描述了undolog日志版本鍊路和readview結合來保證事務的隔離性,接下來再對這個undolog分析一波。

3.1,undolog復原的方式

undolog日志中主要是記錄被修改或者新增的值的記錄,當需要復原時,則将這個存儲undolog的值用來復原。其復原情況主要有如下幾種:

1,當插入一條記錄時,需要把這條記錄的主鍵值記下來,復原的時候隻需要把這個主鍵值對應的記錄删掉。

2,當删除了一條記錄,需要要把這條記錄中的内容都記下來,復原時再把由這些内容組成的記錄插入到表中。

3,當修改了一條記錄,需要要把修改這條記錄前的舊值都記錄下來,復原時再把這條記錄更新為舊值。

3.2,undolog事務id形成機制

在mysql中,主要有隻讀事務和讀寫事務。在隻讀事務中,普通的表是不能進行增删改操作的,而臨時的表是可以進行增删改的;而讀寫事務中,是都可以進行增删改操作的。同時在隻讀事務中,由于臨時表可以進行增删改,是以隻讀事務的臨時表中也是可以産生這個事務id的。

undolog産生的事務id和這個LSN這個序列号是一樣的,也是一個自增的全局變量id,在innodb中,每一行資料都會有一個存儲這個事務id的地方,在之前的行格式中也談到過,這些隐藏聚簇索引id,事務id,復原指針等都存儲在這些行格式,中。如下圖中的row_id,trx_id,roll_ptr等

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

3.3,插入操作

在資料進行插入的操作時,如果此時表中有着二級索引,那麼此時除了向主鍵索引所在的B+樹中存放整行資料,還要向二級索引中存放對應的列以及主鍵id這個字段。如果出現資料復原的情況,那麼不僅要删除主鍵索引中的資料,也要删除二級索引中對應的資料,但是這個id即存在一級索引中,也存在二級索引中,是以undolog在記錄這個插入操作的資料的時候,直接将該行資料的主鍵id值存放在這個undolog的版本鍊路中,如果出現復原的話,是那麼直接通過id删除,就能把資料全部復原回去了。

3.4,删除操作

在資料進行删除時, 會需要用到行格式中的一個delete_mask 字段,這個字段在記錄頭資訊裡面,如果該字段為0,則表示沒有删除,該字段為1,表示已經删除。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

在innodb中,為了保證mvcc的多版本并發控制機制,redolog在删除時引入了一個中間狀态,即在删除時先引用邏輯删除,将delete_mask這個字段将值變為1,随後在事務送出之後,再通過背景啟動一個線程,通過輪詢方式去收集這個字段為1的那些行資料,然後再将值給删除。

由于所有的資料都是通過雙向連結清單的方式串在一起,是以在删除的時候,隻需要将連結清單的前驅和後繼修改即可,并且會将這個需要删除的資料,挂載這個Page Free頁的上面。Page Free頁面上的資料表示該空間上面的頁面可以被重複利用。

3.5,更新操作

在update方面,就會相對的比新增和删除兩種方式更加的麻煩一些,主要分為更新主鍵和不更新主鍵。

3.5.1,不更新主鍵

在不更新主鍵時,又分為就地更新和實體删除再插入。如果在對某個字段做更新時,其要更新的值的長度不變,那麼就會直接選擇就地更新,如原來的值為"張三",現在将值改為"李四",改變的值的長度不變,那麼就不會影響整頁資料的結構,其選擇就地更新;如果更新值的長度和原來的長度不一樣,如原來是一個"張三",現在變成了"張三豐",他的值很明顯不一樣,那麼就會選擇先删除舊記錄,再插入新的記錄。換句話說,就是看空間大小是否發生改變,不變則就地更新,變則先删除後插入。

3.5.2,更新主鍵

更新主鍵操作和删除操作有點類似,為了保證mvcc機制,也是通過記錄頭資訊中的delete mask字段來作為一個中間狀态,即将這個字段的值改為1,然後再事務送出之後再将這條資料删除。删除之後再新增一條資料,根據新的主鍵值在B+樹中找到新的定位,然後将資料新增到此地。就是更新主鍵可以看成是兩步操作,先delete操作,再insert操作,是以在更新主鍵時,就會産生兩條undo日志。

4,事務的整體執行流程

通過上面的redolog和undolog的可知,redolog是為了保證事務的持久性,他具有重做的功能,undolog是為了保證事務的原子性,他具有撤回的功能。是以在開啟一個事務時,可以總結一下各個日志中的作用已經整個事務的執行流程。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

1,以一個更新語句為例,在開啟事務之後,會将磁盤中要更新的資料以頁的方式加載到buffer pool緩沖區中

2,在執行更新語句時,會通過undolog記錄被修改的值。在innodb中,為了保證undolog日志本身的持久性,是以也會通過一個redolog日志來記錄裡面新增的記錄,如undolog的版本控制鍊路新增一個結點時,redolog就會記錄在這條連結清單的什麼位置加入了哪個結點,記錄完之後将記錄加入到Redolog的緩沖區中,再通過一定的方式進行刷盤持久化,是以在整個事務的過程中,redolog比undolog先刷盤。随後将要改變的值加入到buffer pool中

3,在buffer pool中執行sql的更新,将要更新邏輯語句也加入到Redolog緩沖區中,此時也會有一個redolog刷盤操作。

4, 在送出事務時,也會讓對應的redolog日志記錄進行一個刷盤操作。

5,随後undolog會進行刷盤操作,buffer pool中的資料也會通過背景的線程進行一個資料刷盤的操作。

6,在undolog日志和redolog日志,資料頁全部刷盤完成之後,事務執行完畢。

5,redolog和binlog的關系

從下圖來看,redolog是屬于引擎層的,即屬于innodb存儲引擎特有的,而binlog是屬于server層的,即所有的引擎層共有,innodb有,MyIsam也有。從整個流程來看,binlog和redolog都是對一份資料進行的存儲,并且在存儲過程中,需要通過事務标記來保證兩個日志中記錄的值一樣。

【十】深入了解redolog,undolog和binlog的底層原理一, 深入了解Redolog日志底層原理

5.1,為什麼用redolog恢複資料而不用binlog

1,binlog 會記錄表中所有更改操作,包括更新删除資料,更改表結構等等,主要用于人工恢複資料,如開了binlog删庫也不用跑路;而redolog主要是mysql内部使用的,在資料庫突然崩潰mysql内部會自動的通過這個redolog進行一個重做的操作。

2,redolog是Innodb引擎層特有的,binlog是Server層實作的

3,redolog記錄的是實體日志,如在哪一頁哪一行哪個字段做了什麼修改,其效率更高;binlog就是原始的邏輯,和原來的sql差不多

4,redolog預設大小為48M,其記憶體是有限的,是以其内部是通過循環寫的方式去儲存資料,并且其内部隻記錄為刷盤的資料,已刷盤的資料會自動的從這個redolog中删除;binlog采用的是追加寫,所有的記錄都會儲存。而在恢複資料的時候隻需要恢複這部分未刷盤的即可,不需要全部就行一個對比再操作。

5,如果再一個事務中出現兩條相同的sql,如set age = age + 1 where id = 2,如果binlog一條刷盤成功一條刷盤失敗,那麼他是不能區分這兩條是有沒有全部刷盤成功或者失敗的,換句話說就是由于已經有一條成功了,那麼就不能保證是第一條成功了還是第二條成功了,是以不管是全部恢複還是全部不恢複,内部的資料肯定不對;而redolog就不一樣了,隻需要把redolog内部未刷盤的進行一個刷盤操作就好了。

5.2,binlog和redolog如何保證資料的一緻性

mysql中主要使用2pc,兩階段送出來保證資料的一緻性。第一階段就是先做一個準備工作,開啟一個事務送出器,讓所有的資源準備好,然後會去收集所有的資源狀态,當所有資源的狀态都準備好了之後,再進入第二階段,發出一個commit的指令,所有的資源進行一個commit送出。