what:
mysql中binglog使用statement模式會出現,數據同步時:主從數據不一致問題。
why:
主要原因有兩個:
1、記錄的sql上下文不全,例如:下面例子的RC場景;
2、mysql版本迭代,新功能加入,導致不同版本之間的能力不同,從而導致數據不一致。例如:sleep函數在老版本中沒有。
具體例子(sql上下文不全):
說下MySQL5.0之前為啥事務的隔離機制是RC('read-committed)並且存儲格式是Statement時會出現主從復制數據不一致問題。
創建表:
把自動提交關閉 執行兩個會話:
此時查看會話1的提交結果:
dba> select * from t1;
+------+------+
| b1 | b2 |
+------+------+
| 1 | 4 |
| 2 | 8 |
| 3 | 4 |
| 4 | 8 |
| 5 | 4 |
+------+------+
5 rows in set (0.00 sec)
這個結果不會有任何問題。
STATEMENT模式下的主從情況:
假設在RC隔離級別下支持STATEMENT格式的binlog,並且binlog是打開的。binlog的記錄順序是按照事務commit順序為序的。那么顯而易見,binlog中的順序為:
會話2:
dba> set tx_isolation='read-committed';
dba> BEGIN;
dba> update t1 set b2=4 where b2=2;
dba> commit;
會話1:
dba> set tx_isolation='read-committed';
dba> BEGIN;(開啟事務)
dba> update t1 set b2=8 where b2=4;
#會話1進行提交
dba> commit;
那么此時在主從復制的從庫上看到的結果應為:
dba> select * from t1;
+------+------+
| b1 | b2 |
+------+------+
| 1 | 8 |
| 2 | 8 |
| 3 | 8 |
| 4 | 8 |
| 5 | 8 |
+------+------+
5 rows in set (0.00 sec)
可見,在RC隔離級別下,如果支持STATEMENT格式的binlog,是有可能導致主從數據不一致的!
Row和mixed的模式情況:
那么你可能會問,在RC隔離級別下,如果binlog格式為ROW或者MIXED,難道就不會有主從數據不一致的風險嗎?答案是肯定的,如果binlog的格式是ROW或者MIXED,在RC隔離級別下,不會導致主從數據不一致。為什么呢?
因為ROW或者MIXED格式的binlog,是基於數據的變動。在進行update或者delete操作,記錄到binlog,同時會把數據的原始記錄寫入到binlog。所以日志文件會比Statement大些,上述演示過程,binlog的記錄順序仍然是按照事務的commit順序為序的,binlog的順序仍然為:
會話2:
dba> set tx_isolation='read-committed';
dba> BEGIN;
dba> update t1 set b2=4 where b2=2;
dba> commit;
會話1:
dba> set tx_isolation='read-committed';
dba> BEGIN;(開啟事務)
dba> update t1 set b2=8 where b2=4;
#會話1進行提交
dba> commit;
在從庫仍然是按照這個binlog的執行時序,進行更新操作。但不同之處在於。會話2的update操作:
dba> update t1 set b2=4 where b2=2;
寫入到binlog時,會把原始的記錄也記錄下來。它是這樣記錄的:
update dba.t1
where
b1=1
b2=2
set
b1=1
b2=4
update dba.t1
where
b1=3
b2=2
set
b1=3
b2=4
update dba.t1
where
b1=5
b2=2
set
b1=5
b2=4
從庫上會話2的更新操作完成之后,接着執行會話1的更新操作:
dba> update t1 set b2=8 where b2=4;
binlog中的記錄為:
update dba.t1
where
b1=2
b2=4
set
b1=2
b2=8
update dba.t1
where
b1=4
b2=4
set
b1=4
b2=8
這樣從庫看到的結果就是:
dba> select * from t1;
+------+------+
| b1 | b2 |
+------+------+
| 1 | 4 |
| 2 | 8 |
| 3 | 4 |
| 4 | 8 |
| 5 | 4 |
+------+------+
5 rows in set (0.00 sec)
這樣,主從數據就是一致的。