MySQL三大日志及主从复制的原理
MySQL三大日志及主從復制的原理
文章目錄
- MySQL三大日志及主從復制的原理
- 一、binlog
- 1.概念
- 2.分類
- 3.binlog使用場景
- 4.binlog刷盤時機
- 5.binlog日志格式
- 二、redo log
- 1.為什么需要redo log
- 2.redo log基本概念
- 3.redo log記錄形式
- 4.redo log與binlog區別
- 三、undo log
- 四、主從復制的原理
- 1.什么是主從復制?
- 2.主從復制的作用
- 3.主從復制的原理
- 4.總結
日志是mysql數據庫的重要組成部分,記錄著數據庫運行期間各種狀態信息。
mysql日志主要包括錯誤日志、查詢日志、慢查詢日志、事務日志、二進制日志幾大類。
作為開發,我們重點需要關注的是二進制日志(binlog)和事務日志(包括redo log和undo log)。
一、binlog
1.概念
- binlog用于記錄數據庫執行的寫入性操作(不包括查詢)信息,以二進制的形式保存在磁盤中。binlog是mysql的邏輯日志,并且由Server層進行記錄,使用任何存儲引擎的mysql數據庫都會記錄binlog日志。
2.分類
-
邏輯日志:可以簡單理解為記錄的就是sql語句。
-
物理日志:因為mysql數據最終是保存在數據頁中的,物理日志記錄的就是數據頁變更。
-
binlog是通過追加的方式進行寫入的,可以通過max_binlog_size參數設置每個binlog文件的大小,當文件大小達到給定值之后,會生成新的文件來保存日志。
3.binlog使用場景
在實際應用中,binlog的主要使用場景有兩個,分別是主從復制和數據恢復。
- 主從復制:在Master端開啟binlog,然后將binlog發送到各個Slave端,Slave端重放binlog從而達到主從數據一致。
- 數據恢復:通過使用mysqlbinlog工具來恢復數據。
4.binlog刷盤時機
對于InnoDB存儲引擎而言,只有在事務提交時才會記錄biglog,此時記錄還在內存中,那么biglog是什么時候刷到磁盤中的呢?mysql通過sync_binlog參數控制biglog的刷盤時機,取值范圍是0-N:
- 0:不去強制要求,由系統自行判斷何時寫入磁盤;
- 1:每次commit的時候都要將binlog寫入磁盤;
- N:每N個事務,才會將binlog寫入磁盤。
從上面可以看出,sync_binlog最安全的是設置是1,這也是MySQL 5.7.7之后版本的默認值。但是設置一個大一些的值可以提升數據庫性能,因此實際情況下也可以將值適當調大,犧牲一定的一致性來獲取更好的性能。
5.binlog日志格式
binlog日志有三種格式,分別為STATMENT、ROW和MIXED。
在 MySQL 5.7.7之前,默認的格式是STATEMENT,MySQL 5.7.7之后,默認值是ROW。日志格式通過binlog-format指定。
- STATMENT
- 基于SQL語句的復制(statement-based replication, SBR),每一條會修改數據的sql語句會記錄到binlog中。
- 優點:不需要記錄每一行的變化,減少了binlog日志量,節約了IO, 從而提高了性能;
- 缺點:在某些情況下會導致主從數據不一致,比如執行sysdate()、slepp()等。
- ROW
- 基于行的復制(row-based replication, RBR),不記錄每條sql語句的上下文信息,僅需記錄哪條數據被修改了。
- 優點:不會出現某些特定情況下的存儲過程、或function、或trigger的調用和觸發無法被正確復制的問題;
- 缺點:會產生大量的日志,尤其是alter table的時候會讓日志暴漲
- MIXED
- 基于STATMENT和ROW兩種模式的混合復制(mixed-based replication, MBR),一般的復制使用STATEMENT模式保存binlog,對于STATEMENT模式無法復制的操作使用ROW模式保存binlog
二、redo log
1.為什么需要redo log
- 我們都知道,事務的四大特性里面有一個是持久性,具體來說就是只要事務提交成功,那么對數據庫做的修改就被永久保存下來了,不可能因為任何原因再回到原來的狀態。
- 那么mysql是如何保證一致性的呢?最簡單的做法是在每次事務提交的時候,將該事務涉及修改的數據頁全部刷新到磁盤中。
- 但是這么做會有嚴重的性能問題,主要體現在兩個方面:
- 因為Innodb是以頁為單位進行磁盤交互的,而一個事務很可能只修改一個數據頁里面的幾個字節,這個時候將完整的數據頁刷到磁盤的話,太浪費資源了!
- 一個事務可能涉及修改多個數據頁,并且這些數據頁在物理上并不連續,使用隨機IO寫入性能太差!
因此mysql設計了redo log,具體來說就是只記錄事務對數據頁做了哪些修改,這樣就能完美地解決性能問題了(相對而言文件更小并且是順序IO)。
2.redo log基本概念
- redo log包括兩部分:一個是內存中的日志緩沖(redo log buffer),另一個是磁盤上的日志文件(redo log file)。
- mysql每執行一條DML語句,先將記錄寫入redo log buffer,后續某個時間點再一次性將多個操作記錄寫到redo log file。這種先寫日志,再寫磁盤的技術就是MySQL里經常說到的WAL(Write-Ahead Logging) 技術。
- 在計算機操作系統中,用戶空間(user space)下的緩沖區數據一般情況下是無法直接寫入磁盤的,中間必須經過操作系統內核空間(kernel space)緩沖區(OS Buffer)。
- 因此,redo log buffer寫入redo log file實際上是先寫入OS Buffer,然后再通過系統調用fsync()將其刷到redo log file中,過程如下:
- mysql支持三種將redo log buffer寫入redo log file的時機,可以通過innodb_flush_log_at_trx_commit參數配置,各參數值含義如下:
3.redo log記錄形式
- 前面說過,redo log實際上記錄數據頁的變更,而這種變更記錄是沒必要全部保存,因此redo log實現上采用了大小固定,循環寫入的方式,當寫到結尾時,會回到開頭循環寫日志。如下圖:
- 同時我們很容易得知,在innodb中,既有redo log需要刷盤,還有數據頁也需要刷盤,redo log存在的意義主要就是降低對數據頁刷盤的要求。
- 在上圖中,write pos表示redo log當前記錄的LSN(邏輯序列號)位置,check point表示數據頁更改記錄刷盤后對應redo log所處的LSN(邏輯序列號)位置。
- write pos到check point之間的部分是redo log空著的部分,用于記錄新的記錄;
- check point到write pos之間是redo log待落盤的數據頁更改記錄。
- 當write pos追上check point時,會先推動check point向前移動,空出位置再記錄新的日志。
- 啟動innodb的時候,不管上次是正常關閉還是異常關閉,總是會進行恢復操作。因為redo log記錄的是數據頁的物理變化,因此恢復的時候速度比邏輯日志(如binlog)要快很多。
- 重啟innodb時,首先會檢查磁盤中數據頁的LSN,如果數據頁的LSN小于日志中的LSN,則會從checkpoint開始恢復。
- 還有一種情況,在宕機前正處于checkpoint的刷盤過程,且數據頁的刷盤進度超過了日志頁的刷盤進度,此時會出現數據頁中記錄的LSN大于日志中的LSN,這時超出日志進度的部分將不會重做,因為這本身就表示已經做過的事情,無需再重做。
4.redo log與binlog區別
- 由binlog和redo log的區別可知:binlog日志只用于歸檔,只依靠binlog是沒有crash-safe能力的。
- 但只有redo log也不行,因為redo log是InnoDB特有的,且日志上的記錄落盤后會被覆蓋掉。因此需要binlog和redo log二者同時記錄,才能保證當數據庫發生宕機重啟時,數據不會丟失。
三、undo log
數據庫事務四大特性中有一個是原子性,具體來說就是 原子性是指對數據庫的一系列操作,要么全部成功,要么全部失敗,不可能出現部分成功的情況。
實際上,原子性底層就是通過undo log實現的。
- undo log主要記錄了數據的邏輯變化,比如一條INSERT語句,對應一條DELETE的undo log,對于每個UPDATE語句,對應一條相反的UPDATE的undo log,這樣在發生錯誤時,就能回滾到事務之前的數據狀態。
同時,undo log也是MVCC(多版本并發控制)實現的關鍵
四、主從復制的原理
1.什么是主從復制?
- 主從復制,是用來建立一個和主數據庫完全一樣的數據庫環境,稱為從數據庫;主數據庫一般是準實時的業務數據庫。
2.主從復制的作用
- 1、做數據的熱備,作為后備數據庫,主數據庫服務器故障后,可切換到從數據庫繼續工作,避免數據丟失。
- 2、架構的擴展。業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。
- 3、讀寫分離,使數據庫能支撐更大的并發。在報表中尤其重要。由于部分報表sql語句非常的慢,導致鎖表,影響前臺服務。如果前臺使用master,報表使用slave,那么報表sql將不會造成前臺鎖,保證了前臺速度。
3.主從復制的原理
- 數據庫有個bin-log二進制文件,記錄了所有sql語句。
- 我們的目標就是把主數據庫的bin-log文件的sql語句復制過來。
- 讓其在從數據的relay-log重做日志文件中再執行一次這些sql語句即可。
- 下面的主從配置就是圍繞這個原理配置
- 具體需要三個線程來操作:
- binlog輸出線程:每當有從庫連接到主庫的時候,主庫都會創建一個線程然后發送binlog內容到從庫。
在從庫里,當復制開始的時候,從庫就會創建兩個線程進行處理:
- 從庫I/O線程:當START SLAVE語句在從庫開始執行之后,從庫創建一個I/O線程,該線程連接到主庫并請求主庫發送binlog里面的更新記錄到從庫上。從庫I/O線程讀取主庫的binlog輸出線程發送的更新并拷貝這些更新到本地文件,其中包括relay log文件。
- 從庫的SQL線程:從庫創建一個SQL線程,這個線程讀取從庫I/O線程寫到relay log的更新事件并執行。
可以知道,對于每一個主從復制的連接,都有三個線程。擁有多個從庫的主庫為每一個連接到主庫的從庫創建一個binlog輸出線程,每一個從庫都有它自己的I/O線程和SQL線程。
4.總結
- 步驟一:主庫db的更新事件(update、insert、delete)被寫到binlog
- 步驟二:從庫發起連接,連接到主庫
- 步驟三:此時主庫創建一個binlog dump thread線程,把binlog的內容發送到從庫
- 步驟四:從庫啟動之后,創建一個I/O線程,讀取主庫傳過來的binlog內容并寫入到relay log.
- 步驟五:還會創建一個SQL線程,從relay log里面讀取內容,從Exec_Master_Log_Pos位置開始執行讀取到的更新事件,將更新內容寫入到slave的db.
總結
以上是生活随笔為你收集整理的MySQL三大日志及主从复制的原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 力扣--累加数
- 下一篇: 力扣- -正则表达式匹配