MySQL基于行的複制可以最大化保證主從複制的一緻性,對于RBR(基于行複制) 和SBR(基于語句複制),相信大家已經很熟知,下面記錄的是行複制在二進制日志總記錄的情況。
基于行的複制是與位置相關的,binlog裡面隻記錄相關表發生改變的列的資料。其中引入了四個新的事件: Table_map, Write_rows,Delete_rows,Update_rows.
一條語句執行後,在binlog裡面,Table_map事件中包含表ID,和列的類型(沒有列名,slave 可以利用這些資訊對比和master上的表結構是否一緻),後面跟着其他三個事件,結束标志為STMT_END_F.
事件在slave 端執行過程:
1、SQL線程從中繼日中讀取各個事件。
2、對與Table_map事件,SQL線程将提取出表資訊,儲存表的定義。
3、鎖定要改變的表,并檢查master和slave上表結構是否一緻。
4、如果表schema不一緻,則停止複制,否則繼續執行行事件,直至遇到結束标志符:STMT_END_F.
對于Update_rows和Delete_rows事件,SQL線程要先定位到具體的行,查找操作的步驟:
1、主鍵或者
優先選擇slave上的主鍵。這是最好的辦法。當找到比對的主鍵值的時候,就認為已經找到比對的行,行的其他列的内容則不去比對。
2、非空唯一索引掃描
這個也隻比較鍵值
3、其他索引或者全表掃描
此時會比較整個行的資料在master和slave上是否一緻(确實能保證主從複制的一緻性,但也是最慢的)
MySQL在5.1版本以後,提供了基于ROW 模式的複制模式,進而大大提高了資料複制的可靠性;但這種模式在以下場景下會讓備庫的資料延時很大;
1) 存在沒有主鍵的表,導緻備庫應用每個Event 都需要全表掃描 ; 2) 主庫執行了大表DDL 或大事務,導緻備庫也要相同時間執行完 ;
ROW模式資料複制
ROW 模式之是以能保證複制可靠性,是其在BINLOG裡記錄每一行完整記錄,包括所有列的值;在備庫應用日志時,MySQL 會先嘗試用行裡的主鍵去比對自身的記錄,如果沒有主鍵, 則進行全表掃描所有的行,每一行都與日志進行比對,直到發現完全比對的行;
圖2- ROW模式日志比對處理流程
在保證主備資料複制可靠性的前提下,減小主備延時,盡量為每個表建立一個主鍵或唯一索引。