mysql的statement模式主從不一致分析


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)

這樣,主從數據就是一致的。

 


免責聲明!

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



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