Mysql master-master:單表不同步
我有一個master-master MySQL 5.7,除了一個不時出現的錯誤外,一切正常。
如果我
show slave status\G
在server2上執行,我在表上會出現錯誤:... Last_Errno: 1032 Last_Error: Could not execute Update_rows event on table my_database_name.my_table_name; Can't find record in 'my_table_name', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's master log mysql-bin.000120, end_log_pos 83145706 ...
我可以通過執行暫時跳過錯誤:
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
或通過設置
slave-skip-errors = 1032 skip-slave-start
在 server2 的my.cnf中,然後重新啟動 MySQL。
但是,我想永久修復它,所以我檢查了server1的二進制日誌,我發現了這個:
### UPDATE `my_database_name`.`my_table_name` ### WHERE ### @1=140 ### @2='2014:02:02' ### @3=2878 ### @4=3253 ### @5='' ### @6=0.00 ### @7=0 ### @8=35.75 ### @9=0.00 ### @10=0 ### @11=0 ### SET ### @1=140 ### @2='2014:02:02' ### @3=2878 ### @4=3254 ### @5='' ### @6=0.00 ### @7=0 ### @8=35.75 ### @9=0.00 ### @10=0 ### @11=0 # at 83145706
我看到它試圖通過設置第 4 列中的值來更新表,
3254
其中第 4 列本身的值為 3253。無論如何,如果我查看伺服器上的表,它在兩者上都有不同的值:伺服器1:
mysql> select * from my_table_name where my_table_name.id = 140; +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+ | id | col2 | col3 | col4 | col5 | col6 | col7 | col8 | col9 | col10 | col11 | +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+ | 140 | 2014-02-02 | 2878 | 3254 | | 0.00 | 0 | 35.75 | 0.00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 | +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+
伺服器2:
mysql> select * from my_table_name where my_table_name.id = 140; +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+ | id | col2 | col3 | col4 | col5 | col6 | col7 | col8 | col9 | col10 | col11 | +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+ | 140 | 2014-02-02 | 2878 | 3257 | | 0.00 | 0 | 35.75 | 0.00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 | +-----+------------+----------+----------+---------+-----------+---------+---------+-----------+---------------------+---------------------+
考慮到它是master-master,我該如何對齊表格?我想我不能簡單地設置
3253
希望它被二進制日誌更新的值,可以嗎?如果可能的話,我想避免重新同步整個數據庫,因為它真的很大。
謝謝!
您可以使用pt-table-checksum和pt-table-sync線上時執行優化同步,它會回退以避免複製滯後。
假設您在開始時正確設置了複製,這種錯誤表明您正在以非預期/不受支持的方式使用 master/master。Master/master 不支持客戶端和伺服器同時更新同一行,因為它(故意)不解決衝突——這是一個衝突。
- 查詢 A 將值從 2 更改為 3
- 對 B 的查詢將相同的值從 2 更改為 4
- A 看到 B 的複制事件將 2 更改為 4,這是不可能的,因為 value 已經是 3,而不是 2
- B 看到 A 的複制事件將 2 更改為 3,這也是不可能的,因為值已經是 4,而不是 2
跳過錯誤只是忽略了問題。
這是記錄在案的限制。
設置雙向複製時應該注意哪些問題?
MySQL 複製目前不支持主從之間的任何鎖定協議來保證分佈式(跨伺服器)更新的原子性。換句話說,客戶端 A 可以對 co-master 1 進行更新,同時,在它傳播到 co-master 2 之前,客戶端 B 可以對 co-master 2 進行更新,從而更新客戶端 A 的工作方式與它在 co-master 1 上的工作方式不同。因此,當客戶端 A 的更新使其成為 co-master 2 時,它生成的表與 co-master 1 上的表不同,即使在所有更新之後從 co-master 2 也傳播了。這意味著您不應該將兩個伺服器以雙向複製關係連結在一起,除非您確定您的更新可以安全地以任何順序發生,或者除非您以某種方式在客戶端程式碼中處理錯誤排序的更新。
https://dev.mysql.com/doc/refman/5.7/en/faqs-replication.html#faq-replication-how-two-way-problems
實際上同時寫入兩個主機並沒有性能優勢,因為兩個主機仍然必須處理所有寫入,因此您的解決方案可能涉及在任何給定時間將所有寫入發送到單個主機(兩台機器實際上仍然是主機,但是您的應用程序在任何時間點都只處理一個),或者您可能需要重新考慮為什麼要使用循環/環形複製以及更好的選擇是否可能是 Galera 集群。
如果您以非預期方式使用伺服器,則無法“修復”此問題,因為該行為是預期的。