共計 3214 個字符,預計需要花費 9 分鐘才能閱讀完成。
這篇文章主要介紹了 MySQL 部分 5.6 版本罕見復制報錯 ERROR 1837 如何處理,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓丸趣 TV 小編帶著大家一起了解一下。
場景:
1、簡單的一主一從,版本 MySQL-5.6.20
2、master_auto_position=0
3、開啟 gtid
報錯如下:
Last_SQL_Errno: 1837
Last_SQL_Error: Error When @@SESSION.GTID_NEXT is set to a GTID, you must explicitly set it to a different value after a COMMIT or ROLLBACK. Please check GTID_NEXT variable manual page for detailed explanation. Current @@SESSION.GTID_NEXT is c44bd915-440d-11e6-8ea0-6c92bf24b8c0:71844624 . on query. Default database: $db . Query: DELETE FROM `db2`.`tb2`
看完報錯一臉懵逼,莫非主庫在做什么騷操作?
檢查一下主庫 binlog 對應的 GTID 點,可以發現點什么:
(已做數據脫敏,如上兩張表分別用 db1.tb1 和 db2.tb2 來區分)
發現到 GTID 為【c44bd915-440d-11e6-8ea0-6c92bf24b8c0:71844624】和【71844625】之間做了如下操作:
USE db3;
DELETE FROM `db1`.`tb1`;
DELETE FROM `db2`.`tb2`;
DELETE FROM `db_1`.`t1` 與 DELETE FROM `db_2`.`t2` 之間并沒有更多的:SET @@SESSION.GTID_NEXT。
這似乎就違反了 GTID 的限制,一個事務應該對應一個 GTID 號才對。
結合報錯信息,懷疑此時在執行到第二個 DELETE 時,因為第二個 DELETE 沒有對應的 GTID_NEXT,就報錯了:
Last_SQL_Errno: 1837 …… Default database: $db . Query: DELETE FROM `db2`.`tb2`
再檢查一下存儲引擎,發現 db1.tb1 和 db2.tb2 這兩張表均為 memory,即為非事務引擎。
可能與這個有關。
此處,為了修復這個復制故障,在從庫上做如下操作:
〇 SET SESSION sql_log_bin=0;
〇 手動執行未執行的事務,此處為:DELETE FROM `db2`.`tb2`;
〇 SET SESSION sql_log_bin=1;
〇 STOP SLAVE sql_thread; SET @@SESSION.GTID_NEXT= AUTOMATIC START SLAVE sql_thread;
至于為什么在 ENFORCE_GTID_CONSISTENCY 為 ON 的情況下,產生這樣違反 GTID 的 events,我搜了一下 bug 庫:
更多討論如下:
https://bugs.mysql.com/bug.php?id=71695
該問題發生在 5.6.20 及以前的 5.6 版本。
并在 5.6.21 以后的版本修復了這個問題。
在文檔中找到:
Replication: When mysqlbinlog processed multiple binary log files into a single output file, this file was not in a useful
state for point-in-time recovery, when it failed with the error, When @@SESSION.GTID_NEXT is set to a GTID, you must
explicitly set it to a different value after a COMMIT or ROLLBACK. Please check GTID_NEXT variable manual page for
detailed explanation. Current @@SESSION.GTID_NEXT is xyz . When mysqlbinlog processes a binary log containing GTIDs,
it outputs SET gtid_next statements, but gtid_next is set to undefined whenever a commit occurs; this left gtid_next
undefined when the server had finished processing the output from mysqlbinlog. When the next binary log file started
with one or more anonymous statements or transactions, the combination of gtid_next being left undefined at the end
of the first binary log and the second binary log containing anonymous transactions to the error described previously
(Error 1837, ER_GTID_NEXT_TYPE_UNDEFINED_GROUP).
To fix this issue, now, whenever mysqlbinlog encounters this situation, it inserts SET gtid_next = AUTOMATIC
if required to avoid leaving the previous binary log with gtid_next undefined.
In addition, as a result of this fix, mysqlbinlog no longer outputs session variable information for every binary log;
now, this value is printed only once unless it changes. (Bug #18258933, Bug #71695)
大致原因是:
當 mysqlbinlog 處理包含 GTID 的 binlog 時,它會輸出 gtid_next,但是當提交時,gtid_next 會被設置為“undefined”。
當服務器處理完來自 mysqlbinlog 的輸出后,就留下了 binlog undefined。
簡單的來說:
因為 gtid_next 可能會被設置為 undefined,導致復制出現 1837。
為了修復這個問題,在 MySQL5.6.21 版本中,做出了如下修復:
每當 mysqlbinlog 遇到這種情況,會自動加入如下語句:
“SET @@SESSION.GTID_NEXT= AUTOMATIC /* added by mysqlbinlog */ /*!*/;”
以避免使用 gtid_next 保留之前 binlog undefined。
(這個可以在開啟 GTID 時,輕易測試得出)
后來又搜了一下,在使用 INSERT DELAYED 語法時,也可能出現這個問題
雖然文檔描述好像和這個 case 不太像,但總之也是有收獲的:
〇 升級到更高版本的 MySQL。
〇 盡量使用事務引擎,避免在一個事務中同時操作事務表和非事務表的可能性。
(雖然 enforce_gtid_consistency 開啟,但也有可能出現突破 GTID 限制的語句,盡量從業務上限制)
〇 盡量避免使用 INSERT DELAYED 語法。
感謝你能夠認真閱讀完這篇文章,希望丸趣 TV 小編分享的“MySQL 部分 5.6 版本罕見復制報錯 ERROR 1837 如何處理”這篇文章對大家有幫助,同時也希望大家多多支持丸趣 TV,關注丸趣 TV 行業資訊頻道,更多相關知識等著你來學習!