Skip to content

Commit 8258b2f

Browse files
MDEV-37829 Call spider_internal_xa_prepare when XA COMMIT ... ONE PHASE
This allows 1PC XA involving spider tables.
1 parent 9838d7e commit 8258b2f

File tree

5 files changed

+302
-8
lines changed

5 files changed

+302
-8
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# MDEV-37829 XA COMMIT ONE PHASE fails with "This xid does not
3+
# exist" if a trigger references a SPIDER table
4+
#
5+
for master_1
6+
for child2
7+
for child3
8+
set spider_same_server_link= 1;
9+
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
10+
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
11+
CREATE TABLE t (
12+
id INT auto_increment NOT NULL,
13+
name varchar(100) NULL,
14+
CONSTRAINT test_pk PRIMARY KEY (id)
15+
) ENGINE=InnoDB;
16+
Warnings:
17+
Warning 1280 Name 'test_pk' ignored for PRIMARY key.
18+
INSERT INTO t(id, name) VALUES(1,'test1');
19+
CREATE TABLE t2 (
20+
id INT auto_increment NOT NULL,
21+
name varchar(100) NULL,
22+
CONSTRAINT test2_pk PRIMARY KEY (id)
23+
) ENGINE=InnoDB;
24+
Warnings:
25+
Warning 1280 Name 'test2_pk' ignored for PRIMARY key.
26+
CREATE TABLE t3 (
27+
id INT auto_increment NOT NULL,
28+
name varchar(100) NULL,
29+
CONSTRAINT test3_pk PRIMARY KEY (id)
30+
) ENGINE=SPIDER COMMENT='wrapper "mysql", srv "srv", table "t2"';
31+
Warnings:
32+
Warning 1280 Name 'test3_pk' ignored for PRIMARY key.
33+
CREATE PROCEDURE tProc()
34+
BEGIN
35+
# This conditional logic is intentionally FALSE.
36+
# The SELECT on the SPIDER table will never run.
37+
SET @t := FALSE;
38+
IF @t = TRUE THEN
39+
SELECT name INTO @b FROM t3 WHERE id = 1;
40+
END IF;
41+
END$$
42+
CREATE TRIGGER t_au
43+
AFTER UPDATE
44+
ON t FOR EACH ROW
45+
BEGIN
46+
# This condition will also be false in our test case.
47+
IF NEW.name = '3' THEN
48+
CALL tProc();
49+
END IF;
50+
END$$
51+
SELECT "Using 2PC...";
52+
Using 2PC...
53+
Using 2PC...
54+
XA START 'TESTTRX_2P';
55+
UPDATE t SET name = 'abc' WHERE ID = 1;
56+
SHOW WARNINGS;
57+
Level Code Message
58+
XA END 'TESTTRX_2P';
59+
XA PREPARE 'TESTTRX_2P';
60+
XA COMMIT 'TESTTRX_2P';
61+
SELECT "Using 1PC...";
62+
Using 1PC...
63+
Using 1PC...
64+
XA START 'TESTTRX_1P';
65+
UPDATE t SET name = 'abc' WHERE ID = 1;
66+
SHOW WARNINGS;
67+
Level Code Message
68+
XA END 'TESTTRX_1P';
69+
XA COMMIT 'TESTTRX_1P' ONE PHASE;
70+
drop trigger t_au;
71+
drop procedure tProc;
72+
drop table t, t2, t3;
73+
drop server srv;
74+
for master_1
75+
for child2
76+
for child3

storage/spider/mysql-test/spider/bugfix/r/xa_cmd.result

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,79 @@ INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
3434
XA END 'test';
3535
XA PREPARE 'test';
3636
XA COMMIT 'test';
37+
# MDEV-37829 XA COMMIT ONE PHASE fails with "This xid does not
38+
# exist" if a trigger references a SPIDER table
39+
#
40+
# Below we test a version of the MDEV-37829 case that is not a
41+
# no-op on the spider table
42+
XA START 'test1';
43+
INSERT INTO tbl_a (pkey) VALUES (100);
44+
XA END 'test1';
45+
XA COMMIT 'test1' ONE PHASE;
46+
select * from tbl_a;
47+
pkey
48+
0
49+
1
50+
2
51+
3
52+
4
53+
5
54+
6
55+
7
56+
8
57+
9
58+
100
59+
create table t (c int);
60+
insert into t values (1),(2);
61+
CREATE PROCEDURE tProc()
62+
BEGIN
63+
SET @t := TRUE;
64+
IF @t = TRUE THEN
65+
INSERT INTO tbl_a select max(pkey) + 1 from tbl_a;
66+
END IF;
67+
END$$
68+
CREATE TRIGGER t_au
69+
AFTER UPDATE
70+
ON t FOR EACH ROW
71+
BEGIN
72+
IF NEW.c < 50 THEN
73+
CALL tProc();
74+
END IF;
75+
END$$
76+
XA START 'test';
77+
update t set c = c + 1 where c = 1;
78+
XA END 'test';
79+
XA PREPARE 'test';
80+
XA COMMIT 'test';
81+
XA START 'test1';
82+
update t set c = c + 1 where c = 2;
83+
XA END 'test1';
84+
XA COMMIT 'test1' ONE PHASE;
85+
drop table t;
86+
select * from tbl_a;
87+
pkey
88+
0
89+
1
90+
2
91+
3
92+
4
93+
5
94+
6
95+
7
96+
8
97+
9
98+
100
99+
101
100+
102
101+
103
37102
connection child2_1;
38103
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%insert %';
39104
argument
40105
insert into `auto_test_remote`.`tbl_a`(`pkey`)values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)
106+
insert into `auto_test_remote`.`tbl_a`(`pkey`)values(100)
107+
insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`)values(101)
108+
insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`)values(102)
109+
insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`)values(103)
41110
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%insert %'
42111
SELECT pkey FROM tbl_a ORDER BY pkey;
43112
pkey
@@ -51,6 +120,10 @@ pkey
51120
7
52121
8
53122
9
123+
100
124+
101
125+
102
126+
103
54127

55128
deinit
56129
connection master_1;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
--echo #
2+
--echo # MDEV-37829 XA COMMIT ONE PHASE fails with "This xid does not
3+
--echo # exist" if a trigger references a SPIDER table
4+
--echo #
5+
6+
--disable_query_log
7+
--disable_result_log
8+
--source ../../t/test_init.inc
9+
--enable_result_log
10+
--enable_query_log
11+
--source include/have_innodb.inc
12+
set spider_same_server_link= 1;
13+
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
14+
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
15+
16+
# See also spider/bugfix.xa_cmd for a case that is not a no-op on
17+
# the spider table
18+
19+
# 1. SETUP: Create local InnoDB tables and one remote SPIDER table
20+
21+
# Local table to be updated
22+
CREATE TABLE t (
23+
id INT auto_increment NOT NULL,
24+
name varchar(100) NULL,
25+
CONSTRAINT test_pk PRIMARY KEY (id)
26+
) ENGINE=InnoDB;
27+
28+
INSERT INTO t(id, name) VALUES(1,'test1');
29+
30+
# Remote table target
31+
CREATE TABLE t2 (
32+
id INT auto_increment NOT NULL,
33+
name varchar(100) NULL,
34+
CONSTRAINT test2_pk PRIMARY KEY (id)
35+
) ENGINE=InnoDB;
36+
37+
# SPIDER table pointing to the remote target
38+
CREATE TABLE t3 (
39+
id INT auto_increment NOT NULL,
40+
name varchar(100) NULL,
41+
CONSTRAINT test3_pk PRIMARY KEY (id)
42+
) ENGINE=SPIDER COMMENT='wrapper "mysql", srv "srv", table "t2"';
43+
44+
45+
# 2. SETUP: Create a procedure and trigger that reference the SPIDER table
46+
47+
DELIMITER $$;
48+
49+
CREATE PROCEDURE tProc()
50+
BEGIN
51+
# This conditional logic is intentionally FALSE.
52+
# The SELECT on the SPIDER table will never run.
53+
SET @t := FALSE;
54+
IF @t = TRUE THEN
55+
SELECT name INTO @b FROM t3 WHERE id = 1;
56+
END IF;
57+
END$$
58+
59+
CREATE TRIGGER t_au
60+
AFTER UPDATE
61+
ON t FOR EACH ROW
62+
BEGIN
63+
# This condition will also be false in our test case.
64+
IF NEW.name = '3' THEN
65+
CALL tProc();
66+
END IF;
67+
END$$
68+
69+
DELIMITER ;$$
70+
71+
72+
# 3. TEST CASE 1: Two-phase commit
73+
SELECT "Using 2PC...";
74+
XA START 'TESTTRX_2P';
75+
UPDATE t SET name = 'abc' WHERE ID = 1;
76+
SHOW WARNINGS;
77+
XA END 'TESTTRX_2P';
78+
XA PREPARE 'TESTTRX_2P';
79+
XA COMMIT 'TESTTRX_2P';
80+
81+
# 4. TEST CASE 2: One-phase commit
82+
83+
SELECT "Using 1PC...";
84+
XA START 'TESTTRX_1P';
85+
UPDATE t SET name = 'abc' WHERE ID = 1;
86+
SHOW WARNINGS;
87+
XA END 'TESTTRX_1P';
88+
XA COMMIT 'TESTTRX_1P' ONE PHASE;
89+
90+
drop trigger t_au;
91+
drop procedure tProc;
92+
drop table t, t2, t3;
93+
94+
drop server srv;
95+
--disable_query_log
96+
--disable_result_log
97+
--source ../../t/test_deinit.inc
98+
--enable_result_log
99+
--enable_query_log

storage/spider/mysql-test/spider/bugfix/t/xa_cmd.test

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,58 @@ XA END 'test';
4848
XA PREPARE 'test';
4949
XA COMMIT 'test';
5050

51+
--echo # MDEV-37829 XA COMMIT ONE PHASE fails with "This xid does not
52+
--echo # exist" if a trigger references a SPIDER table
53+
--echo #
54+
--echo # Below we test a version of the MDEV-37829 case that is not a
55+
--echo # no-op on the spider table
56+
57+
XA START 'test1';
58+
INSERT INTO tbl_a (pkey) VALUES (100);
59+
XA END 'test1';
60+
XA COMMIT 'test1' ONE PHASE;
61+
62+
select * from tbl_a;
63+
64+
create table t (c int);
65+
insert into t values (1),(2);
66+
67+
DELIMITER $$;
68+
69+
CREATE PROCEDURE tProc()
70+
BEGIN
71+
SET @t := TRUE;
72+
IF @t = TRUE THEN
73+
INSERT INTO tbl_a select max(pkey) + 1 from tbl_a;
74+
END IF;
75+
END$$
76+
77+
CREATE TRIGGER t_au
78+
AFTER UPDATE
79+
ON t FOR EACH ROW
80+
BEGIN
81+
IF NEW.c < 50 THEN
82+
CALL tProc();
83+
END IF;
84+
END$$
85+
86+
DELIMITER ;$$
87+
88+
XA START 'test';
89+
update t set c = c + 1 where c = 1;
90+
XA END 'test';
91+
XA PREPARE 'test';
92+
XA COMMIT 'test';
93+
94+
XA START 'test1';
95+
update t set c = c + 1 where c = 2;
96+
XA END 'test1';
97+
XA COMMIT 'test1' ONE PHASE;
98+
99+
drop table t;
100+
101+
select * from tbl_a;
102+
51103
--connection child2_1
52104
--disable_view_protocol
53105
--disable_ps2_protocol

storage/spider/spd_trx.cc

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,21 +2962,15 @@ int spider_commit(
29622962
{
29632963
if (trx->trx_xa)
29642964
{
2965-
if (trx->internal_xa && !trx->trx_xa_prepared)
2965+
if ((trx->internal_xa || thd->lex->xa_opt == XA_ONE_PHASE) &&
2966+
!trx->trx_xa_prepared)
29662967
{
29672968
if (
29682969
(error_num = spider_internal_xa_prepare(
29692970
thd, trx, table_xa, table_xa_member, TRUE))
29702971
) {
2971-
/*
2972-
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2973-
{
2974-
*/
29752972
/* rollback for semi_trx */
29762973
spider_rollback(hton, thd, all);
2977-
/*
2978-
}
2979-
*/
29802974
DBUG_RETURN(error_num);
29812975
}
29822976
trx->trx_xa_prepared = TRUE;

0 commit comments

Comments
 (0)