MySQL:关于Bug #81119

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 修复版本5.7.18,下面是commit,记录一下后面详细学习。故障下面是commit$ git show a43f7d5a6130550619afad3fb513c98e00dc505ecommit a43f7d5a6130550619afad3fb513c98e00dc505eAuthor: Daogang Qu <bill.

修复版本5.7.18,下面是commit,记录一下后面详细学习。

故障

image.png

下面是commit

$ git show a43f7d5a6130550619afad3fb513c98e00dc505e
commit a43f7d5a6130550619afad3fb513c98e00dc505e
Author: Daogang Qu <bill.qu@oracle.com>
Date:   Wed Jan 20 09:25:36 2016 +0800

    Bug#22130929  GTID_NEXT AND BEGIN BEHAVIOR IS DIFFERENT B/W BINLOG AND BINLOG-LESS SERVER

    Problem
    =======
    When binlog is enabled, we do not save the gtid specified by
    GTID_NEXT into GLOBAL@gtid_executed when committing an empty
    transaction caused by a 'BEGIN' command. But we save the gtid
    into GLOBAL@gtid_executed in the case when binlog is disabled.

    Fix
    ===
    When @@SESSION.GTID_NEXT == 'UUID:NUMBER', the command 'BEGIN' causes
    an error 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET'
    inside an empty/a non-empty transaction regardless of being binlogless
    or not, since it causes an implicit commit like other DDLs. And we do
    not save the gtid specified by GTID_NEXT into GLOBAL@gtid_executed
    in the case.

diff --git a/mysql-test/extra/binlog_tests/gtid_next_begin_caused_trx.test b/mysql-test/extra/binlog_tests/gtid_next_begin_caused_trx.test
new file mode 100644
index 00000000000..1459bcdf775
--- /dev/null
+++ b/mysql-test/extra/binlog_tests/gtid_next_begin_caused_trx.test
@@ -0,0 +1,76 @@
+# ==== Purpose ====
+#
+# When @@SESSION.GTID_NEXT == 'UUID:NUMBER', verify that the command
+# 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# an empty/a non-empty transaction, since it causes an implicit
+# commit. We do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+# ==== Implementation ====
+#
+# 1) Set @@SESSION.GTID_NEXT == 'UUID:NUMBER'
+# 2) Execute a 'BEGIN' command to start a transaction.
+# 3) Execute another 'BEGIN' command to check if it causes an error
+#    'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET'
+#    inside an empty transaction, and we do not save the gtid
+#    specified by GTID_NEXT into GLOBAL@gtid_executed.
+# 4) Execute an 'INSERT' statement.
+# 5) Execute the third 'BEGIN' command to check if it causes an error
+#    'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET'
+#    inside a non-empty transaction, and we do not save the gtid
+#    specified by GTID_NEXT into GLOBAL@gtid_executed.
+# 6) Check that we save the gtid specified by GTID_NEXT into
+#    GLOBAL@gtid_executed when committing the transaction.
+#
+# ==== References ====
+#
+# Bug#22130929  GTID_NEXT AND BEGIN BEHAVIOR IS DIFFERENT B/W BINLOG AND BINLOG-LESS SERVER
+# Caller: suite/binlog/t/binlog_gtid_next_begin_caused_trx.test
+# Caller: t/no_binlog_gtid_next_begin_caused_trx.test
+#
+
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1';
+CREATE TABLE t1 (c1 INT);
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2';
+BEGIN;
+
+--echo #
+--echo # Check that the command 'BEGIN' causes an error
+--echo # 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+--echo # an empty transaction, since it causes an implicit commit. And we
+--echo # do not save the gtid specified by GTID_NEXT into
+--echo # GLOBAL@gtid_executed in the case.
+--echo #
+--error ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET
+BEGIN;
+--let $assert_text= Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2
+--let $assert_cond= "[SELECT @@GLOBAL.GTID_EXECUTED]" = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1"
+--source include/assert.inc
+
+INSERT INTO t1 VALUES (1);
+--echo #
+--echo # Check that the command 'BEGIN' causes an error
+--echo # 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+--echo # a non-empty transaction, since it causes an implicit commit. And
+--echo # we do not save the gtid specified by GTID_NEXT into
+--echo # GLOBAL@gtid_executed in the case.
+--echo #
+--error ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET
+BEGIN;
+--let $assert_text= Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2
+--let $assert_cond= "[SELECT @@GLOBAL.GTID_EXECUTED]" = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1"
+--source include/assert.inc
+
+--echo #
+--echo # Check that we save the gtid specified by GTID_NEXT into
+--echo # GLOBAL@gtid_executed when committing the transaction.
+--echo #
+COMMIT;
+--let $assert_text= Committed gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2
+--let $assert_cond= "[SELECT @@GLOBAL.GTID_EXECUTED]" = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-2"
+--source include/assert.inc
+
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3';
+DROP TABLE t1;
+
diff --git a/mysql-test/r/no_binlog_gtid_next_begin_caused_trx.result b/mysql-test/r/no_binlog_gtid_next_begin_caused_trx.result
new file mode 100644
index 00000000000..44f6216c1b6
--- /dev/null
+++ b/mysql-test/r/no_binlog_gtid_next_begin_caused_trx.result
@@ -0,0 +1,34 @@
+RESET MASTER;
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1';
+CREATE TABLE t1 (c1 INT);
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2';
+BEGIN;
+#
+# Check that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# an empty transaction, since it causes an implicit commit. And we
+# do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+BEGIN;
+ERROR HY000: Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT == 'UUID:NUMBER'.
+include/assert.inc [Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+INSERT INTO t1 VALUES (1);
+#
+# Check that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# a non-empty transaction, since it causes an implicit commit. And
+# we do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+BEGIN;
+ERROR HY000: Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT == 'UUID:NUMBER'.
+include/assert.inc [Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+#
+# Check that we save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed when committing the transaction.
+#
+COMMIT;
+include/assert.inc [Committed gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3';
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/r/binlog_gtid_next_begin_caused_trx.result b/mysql-test/suite/binlog/r/binlog_gtid_next_begin_caused_trx.result
new file mode 100644
index 00000000000..44f6216c1b6
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_gtid_next_begin_caused_trx.result
@@ -0,0 +1,34 @@
+RESET MASTER;
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1';
+CREATE TABLE t1 (c1 INT);
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2';
+BEGIN;
+#
+# Check that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# an empty transaction, since it causes an implicit commit. And we
+# do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+BEGIN;
+ERROR HY000: Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT == 'UUID:NUMBER'.
+include/assert.inc [Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+INSERT INTO t1 VALUES (1);
+#
+# Check that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# a non-empty transaction, since it causes an implicit commit. And
+# we do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+BEGIN;
+ERROR HY000: Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT == 'UUID:NUMBER'.
+include/assert.inc [Dose not commit gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+#
+# Check that we save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed when committing the transaction.
+#
+COMMIT;
+include/assert.inc [Committed gtid aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:2]
+SET GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:3';
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_gtid_next_begin_caused_trx.test b/mysql-test/suite/binlog/t/binlog_gtid_next_begin_caused_trx.test
new file mode 100644
index 00000000000..dc12cb95fa8
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_gtid_next_begin_caused_trx.test
@@ -0,0 +1,30 @@
+# ==== Purpose ====
+#
+# When binlog is enabled and @@SESSION.GTID_NEXT == 'UUID:NUMBER',
+# verify that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# an empty/a non-empty transaction, since it causes an implicit
+# commit. We do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+# ==== Implementation ====
+#
+# See extra/binlog_tests/gtid_next_begin_caused_trx.test
+#
+# ==== References ====
+#
+# Bug#22130929  GTID_NEXT AND BEGIN BEHAVIOR IS DIFFERENT B/W BINLOG AND BINLOG-LESS SERVER
+#
+
+# Test in this file is binlog format agnostic, thus no need
+# to rerun them for every format.
+--source include/have_binlog_format_row.inc
+--source include/have_gtid.inc
+# Test is not required to run against embedded server
+--source include/not_embedded.inc
+
+# Make sure the test is repeatable
+RESET MASTER;
+
+--source extra/binlog_tests/gtid_next_begin_caused_trx.test
+
diff --git a/mysql-test/t/no_binlog_gtid_next_begin_caused_trx-master.opt b/mysql-test/t/no_binlog_gtid_next_begin_caused_trx-master.opt
new file mode 100644
index 00000000000..f3fd62da9b7
--- /dev/null
+++ b/mysql-test/t/no_binlog_gtid_next_begin_caused_trx-master.opt
@@ -0,0 +1,2 @@
+--gtid_mode=ON
+--enforce_gtid_consistency
diff --git a/mysql-test/t/no_binlog_gtid_next_begin_caused_trx.test b/mysql-test/t/no_binlog_gtid_next_begin_caused_trx.test
new file mode 100644
index 00000000000..71f9833827d
--- /dev/null
+++ b/mysql-test/t/no_binlog_gtid_next_begin_caused_trx.test
@@ -0,0 +1,28 @@
+# ==== Purpose ====
+#
+# When binlog is disabled and @@SESSION.GTID_NEXT == 'UUID:NUMBER',
+# verify that the command 'BEGIN' causes an error
+# 'ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET' inside
+# an empty/a non-empty transaction, since it causes an implicit
+# commit. We do not save the gtid specified by GTID_NEXT into
+# GLOBAL@gtid_executed in the case.
+#
+# ==== Implementation ====
+#
+# See extra/binlog_tests/gtid_next_begin_caused_trx.test
+#
+# ==== References ====
+#
+# Bug#22130929  GTID_NEXT AND BEGIN BEHAVIOR IS DIFFERENT B/W BINLOG AND BINLOG-LESS SERVER
+#
+
+
+# Test is not required to run against embedded server
+--source include/not_embedded.inc
+# Should be tested against "binlog disabled" server
+--source include/not_log_bin.inc
+
+# Make sure the test is repeatable
+RESET MASTER;
+
+--source extra/binlog_tests/gtid_next_begin_caused_trx.test
diff --git a/sql/rpl_gtid_execution.cc b/sql/rpl_gtid_execution.cc
index ec36772e8c9..65161e2ca97 100644
--- a/sql/rpl_gtid_execution.cc
+++ b/sql/rpl_gtid_execution.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -453,7 +453,8 @@ enum_gtid_statement_status gtid_pre_statement_checks(THD *thd)
   DBUG_ASSERT(gtid_next->type != AUTOMATIC_GROUP ||
               thd->owned_gtid.is_empty());

-  if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN) &&
+  if ((stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN) ||
+       thd->lex->sql_command == SQLCOM_BEGIN) &&
       thd->in_active_multi_stmt_transaction() &&
       gtid_next->type == GTID_GROUP)
   {
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
SQL 关系型数据库 MySQL
(十八)MySQL排查篇:该如何定位并解决线上突发的Bug与疑难杂症?
前面《MySQL优化篇》、《SQL优化篇》两章中,聊到了关于数据库性能优化的话题,而本文则再来聊一聊关于MySQL线上排查方面的话题。线上排查、性能优化等内容是面试过程中的“常客”,而对于线上遇到的“疑难杂症”,需要通过理性的思维去分析问题、排查问题、定位问题,最后再着手解决问题,同时,如果解决掉所遇到的问题或瓶颈后,也可以在能力范围之内尝试最优解以及适当考虑拓展性。
1153 3
|
关系型数据库 MySQL PHP
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
286 0
|
SQL 缓存 关系型数据库
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
444 0
|
SQL Oracle 关系型数据库
这次被坑惨了,MySQL的隐式转换导致了一个线上BUG
某一天,开发问我,为什么针对一个查询会有两条记录,且其中一条记录并不符合条件select * from tablea where xxno = 170325171202362928;xxno为 170325171202362928 和 170325171202362930的都出现在结果中。 一个等值查询为什么会有另外一个不同值的记录查询出来呢? 我们一起来看看究竟!
|
SQL 关系型数据库 MySQL
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
214 0
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
|
存储 固态存储 关系型数据库
MySQL 5.6 change buffer bug导致crash
Insert buffer 内部标识长度的位图没有正确更新,导致问题
256 0
|
SQL 运维 监控
一个诡异的MySQL查询超时问题,居然隐藏着存在了两年的BUG
一个诡异的MySQL查询超时问题,居然隐藏着存在了两年的BUG
256 0
|
SQL 关系型数据库 MySQL
看来,MySQL next-key lock 的 bug 并没有被修复!
在上一篇文章《MySQL next-key lock 加锁范围是什么?》中已经介绍了主键索引的加锁范围,现在来回顾一下
382 0
|
关系型数据库 MySQL Java
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。
341 0
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。

推荐镜像

更多