關於binlog格式

寫在前面的話

 

1、推薦用mixed,默認使用statement,基於上下文  set session/global binlog_format=mixed;

 

2、二進制日記錄瞭資料庫執行更改的操作,如Insert,Update,Delete等。不包括Select等不影響資料庫記錄的操作

 

3、MySQL記錄的日志有三種模式:STATEMENT、ROW、MIXED

 

4、二進制主要的功能有:復制(Replication)和恢復(Recovery)

 

5、ROW與STATEMENT不同之處主要在於,伺服器負載/一致性兩個方面

 

復制的歷史

 

mysql-3.2 開始支持基於命令的復制,也就是statement-based replication。

 

mysql-5.1 開始支持基於行的復制和混合復制,也就是row-based replication和mixed-based relication。

 

mysql-5.5 開始支持semi-synchronous的復制,也叫半同步復制,目的在於事務環境下保持主從一致。

 

mysql-5.6 開始支持並行復制,但是其並行隻是基於schema的

 

mysql-5.7 開始支持基於組提交的並行復制

 復制的基本過程如下:

 

(1)Slave上面的IO進程連接上Master,並請求從指定日志文件的指定位置(或者從最開始的日志)之後的日志內容

 

(2)Master接收到來自Slave的IO進程的請求後,通過負責復制的IO進程根據請求信息讀取制定日志指定位置之後的日志信息,返回給Slave 的IO進程。返回信息中除瞭日志所包含的信息之外,還包括本次返回的信息已經到Master端的bin-log文件的名稱以及bin-log的位置

 

(3)Slave的IO進程接收到信息後,將接收到的日志內容依次添加到Slave端的relay-log文件的最末端,並將讀取到的Master端的 bin-log的文件名和位置記錄到master-info文件中

 

(4)Slave的Sql進程檢測到relay-log中新增加瞭內容後,會馬上解析relay-log的內容成為在Master端真實執行時候的那些可執行的內容,並在自身執行

 

redolog 和 undolog

 

undolog 實現原子性。每當操作數據前,首先將數據備份到一個地方(這個存儲數據備份的地方稱為undolog)。然後再修改數據。如果出現瞭錯誤或者用戶執行瞭rollback語句,可以利用undolog中的備份將數據恢復到事務開始之前的狀態。

 

redolog 實現持久性。每當操作數據前,將數據真正更改時,先前相關操作寫入重做日志。這樣當斷電,或者一些意外,導致後續任務無法完成時,系統恢復後,可以繼續完成這些更改執行這些操作來恢復數據。 比如某一時刻資料庫down機瞭,有兩個事務,一個事務已經提交,另一個事務正在處理資料庫重啟的時候就要根據日志進行前滾及回退,把已提交事務的更改寫到數據文件,未提交事務的更改恢復到事務開始前的狀態。

 

Row based replication-RBR

 

日志中會記錄成每一行數據被修改的形式,然後在slave端再對相同的數據進行回放,和其他大多數資料庫系統的復制技能一樣

 

優點:bin-log中可以不記錄執行的sql語句的上下文相關的信息,僅僅隻需要記錄那一條記錄被修改瞭,修改成什麼樣瞭。所以row level的日志內容會非常清楚的記錄下每一行數據修改的細節

 

1、任何情況都可以被復制,這對復制來說是最安全可靠的,不會出現某些特定情況下的存儲過程,或function,以及trigger的調用和觸發無法被正確復制的問題

 

2、多數情況下,從伺服器上的表如果有主鍵的話,復制就會快瞭很多,執行 INSERT,UPDATE,DELETE 語句時鎖更少,復制以下幾種語句時的行鎖更少

INSERT … SELECT

包含 AUTO_INCREMENT 字段的 INSERT

 

沒有附帶條件或者並沒有修改很多記錄的 UPDATE 或 DELETE 語句

 

缺點:所有的執行的語句當記錄到日志中的時候,都將以每行記錄的修改來記錄,這樣可能會產生大量的日志內容

 

比如有這樣一條update語句:update product set owner_member_id = 100 where owner_member_id = 1 ,執行之後,日志中記錄的不是這條update語句所對應額事件(MySQL以事件的形式來記錄bin-log日志),而是這條語句所更新的每一條記錄的變化情況,這樣就記錄成很多條記錄被更新的很多個事件。

 

執行alter table之類的語句的時候,產生的日志量是驚人的。因為MySQL對於alter table之類的表結構變更語句的處理方式是整個表的每一條記錄都需要變動,實際上就是重建瞭整個表。那麼該表的每一條記錄都會被記錄到日志中

 

binlog 大瞭很多,復雜的回滾時 binlog 中會包含大量的數據

 

執行 UPDATE 語句時,所有發生變化的記錄都會寫到 binlog 中,這會導致頻繁發生 binlog 的並發寫

 

UDF 產生的大 BLOB 值會導致復制變慢

 

註:采用 RBR 模式後,能處理很多原先出現的主鍵重復問題

 

Statement based replication-SBR

 

每一條會修改數據的sql都會記錄到 master的bin-log中,而且記錄每條語句在執行的時候的一些相關信息,也就是上下文信息

 

優點:不需要記錄每一行數據的變化,減少bin-log日志量,節約IO,提高性能。主從版本可以不一樣,從伺服器版本可以比主伺服器版本高

 

缺點:由於記錄的執行語句,所以為瞭讓這些語句在slave端也能正確執行,那麼他還必須記錄每條語句在執行的時候的一些相關信息,也就是上下文信息

 

另外就是,很多的新功能不斷的加入,使MySQL得復制遇到瞭不小的挑戰。目前已經發現的就有不少情況會造成MySQL的復制出現問題,主要是修改數據的時候使用瞭某些特定的函數或者功能的時候會出現,比如:sleep() 函數在有些版本中就不能真確復制,在存儲過程中使用瞭last_insert_id()函數,可能會使slave和master上得到不一致的id等等

 

1、不是所有的UPDATE語句都能被復制,尤其是包含不確定操作的時候

 

2、調用具有不確定因素的 UDF 時復制也可能出問題,確定瞭的 UDF 也須要在從伺服器上執行

 

3、運用以下函數的語句也不能被復制:LOAD_FILE()、UUID()、USER()、FOUND_ROWS()、SYSDATE() (除非啟動時啟用瞭 –sysdate-is-now 選項)

 

4、INSERT … SELECT 會產生比 RBR 更多的行級鎖,復制須要執行全表掃描(WHERE 語句中沒有運用到索引)的 UPDATE 時,須要比 RBR 請求更多的行級鎖

 

6、對於有 AUTO_INCREMENT 字段的 InnoDB表而言,INSERT 語句會阻塞其他 INSERT 語句

 

7、對於一些復雜的語句,在從伺服器上的耗資源情況會更嚴重,而 RBR 模式下,隻會對那個發生變化的記錄產生影響

 

8、存儲函數(不是存儲流程 )在被調用的同時也會執行一次 NOW() 函數,這個可以說是壞事也可能是好事

 

10、數據表必須幾乎和主伺服器保持一致才行,否則可能會導致復制出錯

 

11、隻支持REPEATABLE READ可重復讀和以上的隔離級別

 

Mixed based replication-MBR

 

觸發器(TRIGGER):

ROW

主上有,從上沒有,復制正常,數據正常。

主上有,從上也有,復制正常,數據正常。

 

STATEMENT/MIXED

主上有,從上沒有,復制正常,數據不正常,觸發器裡面的sql語句沒有執行。

主上有,從上也有,復制正常,數據正常。

 

函數(FUNCTION):

ROW

主上有,從上沒有,復制正常,數據正常。日志裡記錄的是UDF轉換過的結果。

主上有,從上也有,復制正常,數據正常。

 

STATEMENT/MIXED

主上有,從上沒有,復制報錯。從不識別UDF函數。

主上有,從上也有,復制正常,數據正常。

 

存儲過程(STORED PROCEDURES)

ROW

主上有,從上沒有,復制正常,數據正常。記錄的不是call sp,而是SP裡面的sql。

主上有,從上也有,復制正常,數據正常。

 

STATEMENT/MIXED

主上有,從上沒有,復制正常,數據正常。記錄的不是call sp,而是SP裡面的sql。

主上有,從上也有,復制正常,數據正常。

 

事件(event):

ROW

主上有,從上沒有,復制正常,數據正常。記錄的不是計劃,而是EVENT裡面的sql。

主上有,從上也有,復制正常,數據正常。(默認,DISABLE ON SLAVE),ALTER EVENT event_name ENABLE/DISABLE

 

STATEMENT/MIXED

主上有,從上沒有,復制正常,數據正常。記錄的不是計劃,而是EVENT裡面的sql。

主上有,從上也有,復制正常,數據正常。(默認,DISABLE ON SLAVE), ALTER EVENT event_name ENABLE/DISABLE

 

從5.1.8版本開始,MySQL提供瞭除Statement Level和Row Level之外的第三種復制模式:Mixed,實際上就是前兩種模式的結合。在Mixed模式下,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日志形式,也就是在Statement和Row之間選擇一種。新版本中的Statment level還是和以前一樣,僅僅記錄執行的語句。而新版本的MySQL中隊row level模式也被做瞭優化,並不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄,如果sql語句確實就是update或者delete等修改數據的語句,那麼還是會記錄所有行的變更。

 

以下幾種情況下會自動將binlog的模式由 SBR 模式改成 RBR 模式

當DML語句更新一個NDB表時

 

當函數中包含 uuid(),user(),current_user(),found_rows(),row_count(),等不確定函數

 

2個及以上包含 AUTO_INCREMENT 字段的表被更新時

 

行任何 INSERT DELAYED 語句時

 

使用瞭用戶定於的函數(UDF) 時

 

視圖中必須要求運用 RBR 時,例如建立視圖是運用瞭 UUID() 函數

 

使用瞭臨時表(temporary table)

 

 新的基於行模式,用法是 binlog-row-image=minimal 設置該選項後,對於DML操作修改的數據,隻有發生變化的字段才保存到binlog裡面,(insert和delete還是全字段)。這提高瞭master和slave的復制吞吐量,減小瞭binlog的磁盤占用,網絡資源和內存使用。

 

另外,針對系統庫 mysql 裡面的表發生變化時的處理準則如下:

 

1、如果是采用 INSERT,UPDATE,DELETE 直接操作表的情況,則日志格式根據 binlog_format 的設定而記錄

 

2、如果是采用 GRANT,REVOKE,SET PASSWORD 等管理語句來做的話,那麼無論如何 都采用 SBR 模式記錄

 

3、blockhole引擎不支持row格式,ndb引擎不支持statement格式

You May Also Like