MySQL半一致性讀導致語句級Binlog複製錯誤
MySQL事務的隔離級別為read committed(或以下),或者設定了innodb_locks_unsafe_for_binlog引數會啟用半一致性讀特性。
半一致性讀參考:
MySQL官方文件refman-5.6-en.a4.pdf 1833頁 關於innodb_locks_unsafe_for_binlog引數
對於半一致性讀,我感覺一個是違反兩階段鎖,將不符合條件記錄的行級鎖提前釋放。另一個是Update的行如果被鎖定,則返回一個最近提交的版本。
官方文件原文如下:
Enabling innodb_locks_unsafe_for_binlog has additional effects:
? For UPDATE or DELETE statements, InnoDB holds locks only for rows that it updates or deletes.
Record locks for nonmatching rows are released after MySQL has evaluated the WHERE condition.
This greatly reduces the probability of deadlocks, but they can still happen.
? For UPDATE statements, if a row is already locked, InnoDB performs a “semi-consistent” read,
returning the latest committed version to MySQL so that MySQL can determine whether the row
matches the WHERE condition of the UPDATE. If the row matches (must be updated), MySQL reads
the row again and this time InnoDB either locks it or waits for a lock on it.
半一致性讀本身是為了增加併發,但是對於STATEMENT格式的binlog則是致命的錯誤。
實驗環境如下:
初始化資料
CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
COMMIT;
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 2 |
| 2 | 3 |
| 3 | 2 |
| 4 | 3 |
| 5 | 2 |
+---+------+
5 rows in set (0.00 sec)
開啟一個終端A,將b=3的記錄修改為10
然後開啟另外一個終端B,將b=2的記錄修改為3並且提交,
最後提交終端A的事務。
檢視此時的結果
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 3 |
| 2 | 10 |
| 3 | 3 |
| 4 | 10 |
| 5 | 3 |
+---+------+
5 rows in set (0.00 sec)
這個結果沒有任何問題,但是檢視binlog的內容
BEGIN
/*!*/;
# at 2802
#140215 0:07:52 server id 1 end_log_pos 2906 CRC32 0x264b3682 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1392394072/*!*/;
update t set b=3 where b=2
/*!*/;
# at 2906
#140215 0:07:54 server id 1 end_log_pos 2937 CRC32 0x59a3d24d Xid = 63
COMMIT/*!*/;
# at 2937
#140215 0:06:02 server id 1 end_log_pos 3020 CRC32 0x56a9493b Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1392393962/*!*/;
BEGIN
/*!*/;
# at 3020
#140215 0:06:02 server id 1 end_log_pos 3125 CRC32 0x0d874b5d Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1392393962/*!*/;
update t set b=10 where b=3
/*!*/;
# at 3125
#140215 0:08:01 server id 1 end_log_pos 3156 CRC32 0x8fe0dd5d Xid = 61
COMMIT/*!*/;
如果使用binlog複製,則備庫執行的語句如下:
CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
COMMIT;
update t set b=3 where b=2;
commit;
update t set b=10 where b=3;
commit;
備庫執行後的資料則是
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 10 |
| 2 | 10 |
| 3 | 10 |
| 4 | 10 |
| 5 | 10 |
+---+------+
5 rows in set (0.00 sec)
為了避免這個問題,可以將binlog_format設定為ROW。
半一致性讀參考:
MySQL官方文件refman-5.6-en.a4.pdf 1833頁 關於innodb_locks_unsafe_for_binlog引數
對於半一致性讀,我感覺一個是違反兩階段鎖,將不符合條件記錄的行級鎖提前釋放。另一個是Update的行如果被鎖定,則返回一個最近提交的版本。
官方文件原文如下:
Enabling innodb_locks_unsafe_for_binlog has additional effects:
? For UPDATE or DELETE statements, InnoDB holds locks only for rows that it updates or deletes.
Record locks for nonmatching rows are released after MySQL has evaluated the WHERE condition.
This greatly reduces the probability of deadlocks, but they can still happen.
? For UPDATE statements, if a row is already locked, InnoDB performs a “semi-consistent” read,
returning the latest committed version to MySQL so that MySQL can determine whether the row
matches the WHERE condition of the UPDATE. If the row matches (must be updated), MySQL reads
the row again and this time InnoDB either locks it or waits for a lock on it.
半一致性讀本身是為了增加併發,但是對於STATEMENT格式的binlog則是致命的錯誤。
實驗環境如下:
初始化資料
CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
COMMIT;
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 2 |
| 2 | 3 |
| 3 | 2 |
| 4 | 3 |
| 5 | 2 |
+---+------+
5 rows in set (0.00 sec)
開啟一個終端A,將b=3的記錄修改為10
然後開啟另外一個終端B,將b=2的記錄修改為3並且提交,
最後提交終端A的事務。
檢視此時的結果
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 3 |
| 2 | 10 |
| 3 | 3 |
| 4 | 10 |
| 5 | 3 |
+---+------+
5 rows in set (0.00 sec)
這個結果沒有任何問題,但是檢視binlog的內容
BEGIN
/*!*/;
# at 2802
#140215 0:07:52 server id 1 end_log_pos 2906 CRC32 0x264b3682 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1392394072/*!*/;
update t set b=3 where b=2
/*!*/;
# at 2906
#140215 0:07:54 server id 1 end_log_pos 2937 CRC32 0x59a3d24d Xid = 63
COMMIT/*!*/;
# at 2937
#140215 0:06:02 server id 1 end_log_pos 3020 CRC32 0x56a9493b Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1392393962/*!*/;
BEGIN
/*!*/;
# at 3020
#140215 0:06:02 server id 1 end_log_pos 3125 CRC32 0x0d874b5d Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1392393962/*!*/;
update t set b=10 where b=3
/*!*/;
# at 3125
#140215 0:08:01 server id 1 end_log_pos 3156 CRC32 0x8fe0dd5d Xid = 61
COMMIT/*!*/;
如果使用binlog複製,則備庫執行的語句如下:
CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
COMMIT;
update t set b=3 where b=2;
commit;
update t set b=10 where b=3;
commit;
備庫執行後的資料則是
mysql> select * from t;
+---+------+
| a | b |
+---+------+
| 1 | 10 |
| 2 | 10 |
| 3 | 10 |
| 4 | 10 |
| 5 | 10 |
+---+------+
5 rows in set (0.00 sec)
為了避免這個問題,可以將binlog_format設定為ROW。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1081678/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- merge語句導致的ORA錯誤分析
- MySQL半同步複製資料最終一致性驗證MySql
- MySQL 網路導致的複製報錯案例MySql
- MySQL#複製 - 原生複製的一致性探討MySql
- 半同步複製報錯mysql8.0.25MySql
- MySQL 主從複製,常見的binlog錯誤及解決方法MySql
- mysql replication複製錯誤(zt)MySql
- MySQL 半同步複製MySql
- MySQL半同步複製MySql
- MySQL 8 複製(二)——半同步複製MySql
- 解讀MySQL雙主複製的主備資料一致性GPMySql
- 【MySQL】複製1236錯誤(不同版本間binlog_checksum配置問題)MySql
- load data語句如何保證主備複製資料一致性(一)
- MySQL5.7半同步複製報錯案例分析MySql
- mysql 5.7半同步複製MySql
- MySQL的半同步複製MySql
- MySQL主從複製之半同步複製MySql
- mysql一致性讀MySql
- MySQL半一致性讀原理解析-從原始碼角度解析MySql原始碼
- MySQL的非同步複製和半同步複製MySql非同步
- MySQL主從複製、半同步複製和主主複製MySql
- MySQL e二級索引上的一致性讀MySql索引
- Mysql5.7半同步複製MySql
- 【MySQL】半同步與增強半同步複製MySql
- MySQL主從複製錯誤——列型別轉換錯誤MySql型別
- sqlplus註釋導致語句重複執行SQL
- Mysql主機斷電導致複製出錯 server_errno=1236MySqlServer
- MySQL主從複製、半同步複製和主主複製概述MySql
- MySQL5.7主從複製-半同步複製搭建MySql
- MySQL 主從複製錯誤1837MySql
- MySQL GTID複製錯誤修復演示MySql
- sql語句錯誤SQL
- MySQL的主從複製、半同步複製、主主複製詳解MySql
- 配置mysql5.5主從複製、半同步複製、主主複製MySql
- mysql半同步複製的設定MySql
- MySQL 半同步複製+MMM架構MySql架構
- MySQL半同步複製--after_rollbackMySql
- mysql5.5半同步複製探究MySql