Skip to content

Commit 0c79729

Browse files
author
Pedro Figueiredo
committed
BUG#27928837 `HEAD->VARIABLES.GTID_NEXT.TYPE != UNDEFINED_GTID'
Description ----------- The assertion with failing condition `head->variables.gtid_next.type != UNDEFINED_GROUP`, in function ` bool MYSQL_BIN_LOG::assign_automatic_gtids_to_flush_group(THD*)`, is generated while running an `XA ROLLBACK` statement with non-existing XID and `GTID_NEXT` is set to a specific UUID. Analysis -------- The *8de09762684577f4a891bba3344c79666d185006* commit altered the behaviour of `MYSQL_BIN_LOG::rollback` regarding XA transactions by always invoking `gtid_state->update_on_commit()` in order to persist the executed GTID. However, the specified code was introduced below the goto tag `end`, the default fallback goto tag - even for errors - meaning that the `gtid_state->update_on_commit()` will be invoked even if the `XA ROLLBACK` fails with an error - which is the case for this bug. Fix --- Only invoke `gtid_state->update_on_commit()`, while processing an `XA ROLLBACK`, if no error occurs.
1 parent 4736e3b commit 0c79729

File tree

5 files changed

+199
-3
lines changed

5 files changed

+199
-3
lines changed

mysql-test/include/rpl_set_gtid_mode.inc

+18-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# [--let $rpl_skip_sync= 1]
1717
# [--let $rpl_only_running_threads= 1]
1818
# [--let $rpl_debug= 1]
19+
# [--let $no_extra_info= 0]
1920
# --source include/rpl_set_gtid_mode.inc
2021
#
2122
# Parameters:
@@ -42,6 +43,12 @@
4243
#
4344
# $rpl_debug=1
4445
# See include/rpl_init.inc
46+
#
47+
# $no_extra_info=0
48+
# Do not print the mode and server after the include file name. This option
49+
# allows to easly support tests that may invoke with dynamic parameter
50+
# values.
51+
#
4552

4653
# Get the new gtid_mode
4754
--let $_rsgm_new_mode= $rpl_gtid_mode
@@ -75,7 +82,17 @@ if ($_rsgm_server_list == '')
7582
}
7683
}
7784

78-
--let $include_filename= rpl_set_gtid_mode.inc [$_rsgm_new_mode on servers $_rsgm_server_list]
85+
--let $_rsgm_mute= $no_extra_info
86+
if ($_rsgm_mute == '')
87+
{
88+
--let $_rsgm_mute= 0
89+
}
90+
91+
--let $include_filename= rpl_set_gtid_mode.inc
92+
if ($_rsgm_mute == 0)
93+
{
94+
--let $include_filename= rpl_set_gtid_mode.inc [$_rsgm_new_mode on servers $_rsgm_server_list]
95+
}
7996
--source include/begin_include_file.inc
8097

8198
if ($rpl_inited)

mysql-test/suite/binlog/r/binlog_gtid_next_xa.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ one
787787
0
788788
SELECT count(*) FROM mysql.gtid_executed FOR UPDATE;
789789
count(*)
790-
16
790+
17
791791
Warnings:
792792
Warning 3129 Please do not modify the gtid_executed table. This is a mysql internal system table to store GTIDs for committed transactions. Modifying it can lead to an inconsistent GTID state.
793793
[connection master]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
CREATE TABLE t2(a INT);
2+
SET @@AUTOCOMMIT=0;
3+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1';
4+
INSERT INTO t2 VALUES(1);
5+
XA ROLLBACK 'xa1';
6+
ERROR XAE04: XAER_NOTA: Unknown XID
7+
SET @@AUTOCOMMIT=1;
8+
SET @@AUTOCOMMIT=0;
9+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:2';
10+
INSERT INTO t2 VALUES(2);
11+
XA COMMIT 'xa1';
12+
ERROR XAE04: XAER_NOTA: Unknown XID
13+
SET @@AUTOCOMMIT=1;
14+
XA START 'xa1';
15+
XA END 'xa1';
16+
XA PREPARE 'xa1';
17+
SET @@AUTOCOMMIT=0;
18+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:3';
19+
INSERT INTO t2 VALUES(3);
20+
XA ROLLBACK 'xa1';
21+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state
22+
SET @@AUTOCOMMIT=1;
23+
SET @@AUTOCOMMIT=0;
24+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:4';
25+
INSERT INTO t2 VALUES(4);
26+
XA COMMIT 'xa1';
27+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state
28+
SET @@AUTOCOMMIT=1;
29+
include/assert.inc [All inserts were committed, XA statements and respective failures, were disregarded]
30+
SET SESSION GTID_NEXT='AUTOMATIC';
31+
DROP TABLE t2;
32+
SET @@AUTOCOMMIT=DEFAULT_AUTOCOMMIT;
33+
RESET MASTER;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# ==== Purpose ====
2+
#
3+
# The purpose of this test is to ensure that the server properly disregards XA
4+
# transaction related statements that try to operate upon an unknown XID, when
5+
# on SBR.
6+
#
7+
# ==== Requirements ====
8+
#
9+
# R1. Ensure that execution proceeds normaly after trying - and failling - to
10+
# execute `XA COMMIT / ROLLBACK` with an unkown XID.
11+
#
12+
# ==== Implementation ====
13+
#
14+
# Ensure that the server properly disregards XA related statements that operate
15+
# on unknown XIDs given the following setup / statements combinations:
16+
#
17+
# TC1. Manual GTID and apply `XA ROLLBACK` with unkown XID
18+
# --------------------------------------------------------
19+
# 1) Ensure that `AUTOCOMMIT` is OFF.
20+
# 2) Set `GTID_NEXT` to manually introduced value.
21+
# 3) Execute a DML statement.
22+
# 4) Execute `XA ROLLBACK` with an unknown XID.
23+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
24+
# commited.
25+
#
26+
# TC2. Manual GTID and apply `XA ROLLBACK` with unkown XID
27+
# --------------------------------------------------------
28+
# 1) Ensure that `AUTOCOMMIT` is OFF.
29+
# 2) Set `GTID_NEXT` to manually introduced value.
30+
# 3) Execute a DML statement.
31+
# 4) Execute `XA ROLLBACK` with an unknown XID.
32+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
33+
# commited.
34+
#
35+
# TC3. Manual GTID and apply `XA ROLLBACK` to an existent XA transaction
36+
# --------------------------------------------------------------------
37+
# 1) Ensure that `AUTOCOMMIT` is OFF.
38+
# 2) Set `GTID_NEXT` to manually introduced value.
39+
# 3) Execute a DML statement.
40+
# 4) Execute `XA ROLLBACK` with an existent XID.
41+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
42+
# commited.
43+
#
44+
# TC4. Manual GTID and apply `XA COMMIT` to an existent XA transaction
45+
# -----------------------------------------------------------------------
46+
# 1) Ensure that `AUTOCOMMIT` is OFF.
47+
# 2) Set `GTID_NEXT` to manually introduced value.
48+
# 3) Execute a DML statement.
49+
# 4) Execute `XA COMMIT` with an existent XID.
50+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
51+
# commited.
52+
#
53+
# ==== References ====
54+
#
55+
# BUG#27928837 `HEAD->VARIABLES.GTID_NEXT.TYPE != UNDEFINED_GTID`
56+
57+
--source include/have_gtid.inc
58+
59+
--let $current_autocommit= `SELECT @@AUTOCOMMIT`
60+
61+
CREATE TABLE t2(a INT);
62+
63+
# TC1. Manual GTID and apply `XA ROLLBACK` with unkown XID
64+
# --------------------------------------------------------
65+
# 1) Ensure that `AUTOCOMMIT` is OFF.
66+
SET @@AUTOCOMMIT=0;
67+
# 2) Set `GTID_NEXT` to manually introduced value.
68+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1';
69+
# 3) Execute a DML statement.
70+
INSERT INTO t2 VALUES(1);
71+
# 4) Execute `XA ROLLBACK` with an unknown XID.
72+
--error ER_XAER_NOTA
73+
XA ROLLBACK 'xa1';
74+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
75+
# commited.
76+
SET @@AUTOCOMMIT=1;
77+
#
78+
79+
# TC2. Manul GTID and apply `XA ROLLBACK` with unkown XID
80+
# -----------------------------------------------------------
81+
# 1) Ensure that `AUTOCOMMIT` is OFF.
82+
SET @@AUTOCOMMIT=0;
83+
# 2) Set `GTID_NEXT` to manually introduced value.
84+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:2';
85+
# 3) Execute a DML statement.
86+
INSERT INTO t2 VALUES(2);
87+
# 4) Execute `XA COMMIT` with an unknown XID.
88+
--error ER_XAER_NOTA
89+
XA COMMIT 'xa1';
90+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
91+
# commited.
92+
SET @@AUTOCOMMIT=1;
93+
#
94+
95+
--connect (other_conn, 127.0.0.1,root,,test,$MASTER_MYPORT,)
96+
XA START 'xa1';
97+
XA END 'xa1';
98+
XA PREPARE 'xa1';
99+
--disconnect other_conn
100+
101+
--connection default
102+
# TC3. Manual GTID and apply `XA ROLLBACK` to an existent XA transaction
103+
# --------------------------------------------------------------------
104+
# 1) Ensure that `AUTOCOMMIT` is OFF.
105+
SET @@AUTOCOMMIT=0;
106+
# 2) Set `GTID_NEXT` to manually introduced value.
107+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:3';
108+
# 3) Execute a DML statement.
109+
INSERT INTO t2 VALUES(3);
110+
# 4) Execute `XA ROLLBACK` with an existent XID.
111+
--error ER_XAER_RMFAIL
112+
XA ROLLBACK 'xa1';
113+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
114+
# commited.
115+
SET @@AUTOCOMMIT=1;
116+
#
117+
118+
# TC4. Manual GTID and apply `XA COMMIT` to an existent XA transaction
119+
# -----------------------------------------------------------------------
120+
# 1) Ensure that `AUTOCOMMIT` is OFF.
121+
SET @@AUTOCOMMIT=0;
122+
# 2) Set `GTID_NEXT` to manually introduced value.
123+
SET SESSION GTID_NEXT='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:4';
124+
# 3) Execute a DML statement.
125+
INSERT INTO t2 VALUES(4);
126+
# 4) Execute `XA COMMIT` with an existent XID.
127+
--error ER_XAER_RMFAIL
128+
XA COMMIT 'xa1';
129+
# 5) Set `AUTOCOMMIT` to the default value so that the DML statement gets
130+
# commited.
131+
SET @@AUTOCOMMIT=1;
132+
#
133+
134+
--let $assert_text= All inserts were committed, XA statements and respective failures, were disregarded
135+
--let $assert_cond= "[SELECT COUNT(1) FROM t2]" = "4"
136+
--source include/assert.inc
137+
138+
SET SESSION GTID_NEXT='AUTOMATIC';
139+
140+
DROP TABLE t2;
141+
142+
--replace_result $current_autocommit DEFAULT_AUTOCOMMIT
143+
--eval SET @@AUTOCOMMIT=$current_autocommit
144+
145+
RESET MASTER;

sql/binlog.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -2576,7 +2576,8 @@ int MYSQL_BIN_LOG::rollback(THD *thd, bool all)
25762576
{
25772577
error= ha_rollback_low(thd, all);
25782578
/* Successful XA-rollback commits the new gtid_state */
2579-
gtid_state->update_on_commit(thd);
2579+
if (!error && !thd->is_error())
2580+
gtid_state->update_on_commit(thd);
25802581
}
25812582
/*
25822583
When a statement errors out on auto-commit mode it is rollback

0 commit comments

Comments
 (0)