共计 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 行业资讯频道,更多相关知识等着你来学习!