MySQL三種日志之binlog/redo log/undo log


   0. MySql的3種日志

 

    MySQL數據庫為什么可以實現主從復制,持久化,回滾的呢?

其實關鍵在於MySQL里的三種log,分別是:

- binlog
- redo log
- undo log

1. 什么是binlog

binlog是用於記錄數據庫表結構和表數據變更的二進制日志

eg:
insert、update、delete、create、truncate等等操作。
不會記錄select、show操作,因為沒有對數據本身發生變更。
-----------------------------------------------------------------------------------
binlog會記錄下每條變更的sql語句,還有執行開始時間,結束時間,事務id等等信息。

binlog是通過追加的方式進行寫入的,可以通過max_binlog_size參數設置每個binlog文件的大小,
當文件大小達到給定值之后,會生成新的文件來保存日志。
 
2. binlog詳細介紹

    - 查看binlog是否打開

     使用命令show variables like '%log_bin%'

   - 開啟binlog

    找到my.cnf配置文件,增加下面配置(mysql版本5.7.31):
    

# 打開binlog
log-bin=mysql-bin
# 選擇ROW(行)模式
binlog-format=ROW

 

修改后,重啟mysql,配置生效。

執行SHOW MASTER STATUS;可以查看當前寫入的binlog文件名。

 

- binlog使用場景

主從復制和數據恢復。

1. 主從復制:
在Master端開啟binlog, 從機訂閱binlog日志的信息。
然后將binlog發送到各個Slave端,Slave端重放binlog從而達到主從數據一致。
-----------------------------------------------------------------------------------
2. 數據恢復:
通過使用mysqlbinlog工具來恢復數據。
指定--start-position和--stop-position,或者指定--start-datetime和--stop-datetime,那么就可以恢復指定區間的數據。

 

binlog主從復制(見下圖)

 

- binlog刷盤時機

對於InnoDB存儲引擎而言,只有在事務提交時才會記錄biglog,此時記錄還在內存中。
mysql通過sync_binlog參數控制biglog的刷盤時機,
取值范圍是0-N:

0:不去強制要求,由系統自行判斷何時寫入磁盤;
1:每次commit的時候都要將binlog寫入磁盤;
N:每N個事務,才會將binlog寫入磁盤。

從上面可以看出,sync_binlog最安全的是設置是1,這也是MySQL 5.7.7之后版本的默認值。
但是設置一個大一些的值可以提升數據庫性能,

因此實際情況下也可以將值適當調大,犧牲一定的一致性來獲取更好的性能。

- 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。

 

3. redo log

為什么需要redo log?

事務的四大特性里面有一個是持久性,具體來說就是只要事務提交成功,那么對數據庫做的修改就被永久保存下來了,
不可能因為任何原因再回到原來的狀態。
那么mysql是如何保證一致性的呢?最簡單的做法是在每次事務提交的時候,
將該事務涉及修改的數據頁全部刷新到磁盤中。但是這么做會有嚴重的性能問題,

主要體現在兩個方面:
1. 因為Innodb是以頁為單位進行磁盤交互的,而一個事務很可能只修改一個數據頁里面的幾個字節,
   這個時候將完整的數據頁刷到磁盤的話,太浪費資源了!

2. 一個事務可能涉及修改多個數據頁,並且這些數據頁在物理上並不連續,使用隨機IO寫入性能太差!

因此mysql設計了redo log,
具體來說就是只記錄事務對數據頁做了哪些修改,
這樣就能完美地解決性能問題了(相對而言文件更小並且是順序IO)。

 

redo log結構(見下圖)

 

redo log與binlog區別

 

 

 

4. undo log

undo log的作用主要用於回滾,mysql數據庫的事務的原子性就是通過undo log實現的。

 

我們都知道原子性是指對數據庫的一系列操作,要么全部成功,要么全部失敗。
undo log主要存儲的是數據的邏輯變化日志,比如說我們要insert一條數據,
那么undo log就會生成一條對應的delete日志。
簡單點說,undo log記錄的是數據修改之前的數據,因為需要支持回滾。
那么當需要回滾時,只需要利用undo log的日志就可以恢復到修改前的數據。
undo log另一個作用是實現多版本控制(MVCC),undo記錄中包含了記錄更改前的鏡像,
如果更改數據的事務未提交,對於隔離級別大於等於read commit的事務而言,
不應該返回更改后數據,而應該返回老版本的數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM