Skip to content

Commit 770fa15

Browse files
committed
Bug#36784284 - Secondary fails when executing a CREATE TABLE SELECT from an async channel
Running a "CREATE TABLE ... AS SELECT" statement on a source coming from an asynchronous channel to Group Replication, causes errors on the replica. Group replication uses LEX::sql_command to identify the statement type and SELECT query block checks to identify statement as "CREATE TABLE ... AS SELECT". When using "CREATE TABLE ... AS SELECT" for a table with an engine supporting Atomic DDL, the binary log on the source server will contain the statement in the following format: CREATE TABLE ... START TRANSACTION TABLE MAP ROW EVENT ROW EVENT ROW EVENT XID / COMMIT While committing this event (the 'CREATE TABLE ... AS SELECT' statement) on the group replication node using the XID / COMMIT (sql_command == SQL_END)statement, logic to identify "CREATE TABLE ... AS SELECT" fails now. This occurs because the conditions for recognizing the statement as such are not satisfied on the replica. As consequence, Group Replication includes inaccurate information in the metadata associated with the event. Hence, applying event on the secondary in the group replication fails. To fix this issue, logic to identify "CREATE TABLE ... SELECT" statement in Group Replication is extended to check if statement is a transactional DDL. Flag to indicate transactional DDL is set only while executing "CREATE TABLE ... AS SELECT" statement at replica. Change-Id: I19703d8d9040843e45afb031cbc6f86537741618
1 parent 6012ed9 commit 770fa15

File tree

5 files changed

+172
-2
lines changed

5 files changed

+172
-2
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
include/group_replication.inc [rpl_server_count=3]
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information.
5+
[connection server1]
6+
# Bug#36784284 - Secondary fails when executing a CREATE TABLE SELECT from
7+
# an async channel
8+
9+
############################################################
10+
# 1. Setup Group Replication on server 1 and 2.
11+
[connection server1]
12+
include/start_and_bootstrap_group_replication.inc
13+
[connection server2]
14+
include/start_group_replication.inc
15+
include/rpl_gr_wait_for_number_of_members.inc
16+
17+
############################################################
18+
# 2. Setup a asynchronous replication connection from server 3
19+
# into group (server 1)
20+
[connection server1]
21+
CHANGE REPLICATION SOURCE TO SOURCE_HOST="127.0.0.1", SOURCE_USER="root", SOURCE_PASSWORD="", SOURCE_PORT=SERVER_3_PORT, SOURCE_AUTO_POSITION=1, REQUIRE_TABLE_PRIMARY_KEY_CHECK=OFF, REQUIRE_ROW_FORMAT=1 FOR CHANNEL "";
22+
Warnings:
23+
Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
24+
Note 1760 Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information.
25+
include/start_slave.inc
26+
27+
############################################################
28+
# 3. Execute CREATE TABLE ... SELECT statements on server 3.
29+
[connection server3]
30+
CREATE TABLE t1 (c1 INT, c2 VARCHAR(80),PRIMARY KEY (c1));
31+
CREATE TABLE t2 (PRIMARY KEY (c1)) AS SELECT * FROM t1;
32+
INSERT INTO t1 VALUES (1, 'aaaa');
33+
CREATE TABLE t3 (PRIMARY KEY (c1)) AS SELECT * FROM t1;
34+
35+
############################################################
36+
# 4. Wait until transactions executed on server 3 are
37+
# applied on group.
38+
include/sync_slave_sql_with_master.inc
39+
[connection server3]
40+
include/sync_slave_sql_with_master.inc
41+
42+
############################################################
43+
# 5. Cleanup
44+
[connection server3]
45+
DROP TABLE t1, t2, t3;
46+
include/sync_slave_sql_with_master.inc
47+
[connection server3]
48+
include/sync_slave_sql_with_master.inc
49+
[connection server1]
50+
include/stop_slave.inc
51+
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=0 FOR CHANNEL "";
52+
include/group_replication_end.inc
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!include ../my.cnf
2+
3+
[mysqld.1]
4+
5+
[mysqld.2]
6+
7+
[mysqld.3]
8+
9+
[ENV]
10+
SERVER_MYPORT_3= @mysqld.3.port
11+
SERVER_MYSOCK_3= @mysqld.3.socket
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
################################################################################
2+
# Validate the behaviour of 'CREATE TABLE ... AS SELECT' coming from an async
3+
# replication channel to group replication.
4+
#
5+
# Bug#36784284 - Secondary fails when executing a CREATE TABLE SELECT from
6+
# an async channel
7+
#
8+
# 1. Setup Group Replication on server 1 and 2.
9+
# 2. Setup a asynchronous replication connection from server 3
10+
# into group (server 1)
11+
# 3. Execute CREATE TABLE ... SELECT statements on server 3.
12+
# 4. Wait until transactions executed on server 3 are applied on group.
13+
# Secondary should not fail when executing a CREATE TABLE SELECT.
14+
# 5. Clean-up
15+
################################################################################
16+
17+
--source include/have_group_replication_plugin.inc
18+
--let $rpl_skip_group_replication_start= 1
19+
--let $rpl_server_count= 3
20+
--source include/group_replication.inc
21+
22+
--echo # Bug#36784284 - Secondary fails when executing a CREATE TABLE SELECT from
23+
--echo # an async channel
24+
25+
--echo
26+
--echo ############################################################
27+
--echo # 1. Setup Group Replication on server 1 and 2.
28+
--let $rpl_connection_name= server1
29+
--source include/rpl_connection.inc
30+
--source include/start_and_bootstrap_group_replication.inc
31+
32+
--let $rpl_connection_name= server2
33+
--source include/rpl_connection.inc
34+
--source include/start_group_replication.inc
35+
36+
--let $group_replication_number_of_members= 2
37+
--source include/gr_wait_for_number_of_members.inc
38+
39+
40+
--echo
41+
--echo ############################################################
42+
--echo # 2. Setup a asynchronous replication connection from server 3
43+
--echo # into group (server 1)
44+
--let $rpl_connection_name= server1
45+
--source include/rpl_connection.inc
46+
--replace_result $SERVER_MYPORT_3 SERVER_3_PORT
47+
--eval CHANGE REPLICATION SOURCE TO SOURCE_HOST="127.0.0.1", SOURCE_USER="root", SOURCE_PASSWORD="", SOURCE_PORT=$SERVER_MYPORT_3, SOURCE_AUTO_POSITION=1, REQUIRE_TABLE_PRIMARY_KEY_CHECK=OFF, REQUIRE_ROW_FORMAT=1 FOR CHANNEL ""
48+
--source include/start_slave.inc
49+
50+
--echo
51+
--echo ############################################################
52+
--echo # 3. Execute CREATE TABLE ... SELECT statements on server 3.
53+
--let $rpl_connection_name= server3
54+
--source include/rpl_connection.inc
55+
56+
CREATE TABLE t1 (c1 INT, c2 VARCHAR(80),PRIMARY KEY (c1));
57+
CREATE TABLE t2 (PRIMARY KEY (c1)) AS SELECT * FROM t1;
58+
59+
INSERT INTO t1 VALUES (1, 'aaaa');
60+
CREATE TABLE t3 (PRIMARY KEY (c1)) AS SELECT * FROM t1;
61+
62+
--echo
63+
--echo ############################################################
64+
--echo # 4. Wait until transactions executed on server 3 are
65+
--echo # applied on group.
66+
--let $sync_slave_connection= server1
67+
--source include/sync_slave_sql_with_master.inc
68+
69+
--let $rpl_connection_name= server3
70+
--source include/rpl_connection.inc
71+
--let $sync_slave_connection= server2
72+
--source include/sync_slave_sql_with_master.inc
73+
74+
--echo
75+
--echo ############################################################
76+
--echo # 5. Cleanup
77+
--let $rpl_connection_name= server3
78+
--source include/rpl_connection.inc
79+
DROP TABLE t1, t2, t3;
80+
81+
--let $sync_slave_connection= server1
82+
--source include/sync_slave_sql_with_master.inc
83+
84+
--let $rpl_connection_name= server3
85+
--source include/rpl_connection.inc
86+
--let $sync_slave_connection= server2
87+
--source include/sync_slave_sql_with_master.inc
88+
89+
--let $rpl_connection_name= server1
90+
--source include/rpl_connection.inc
91+
--source include/stop_slave.inc
92+
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=0 FOR CHANNEL "";
93+
94+
--source include/group_replication_end.inc

sql/replication.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ typedef struct Trans_param {
194194

195195
/*
196196
Flag to identify a 'CREATE TABLE ... AS SELECT'.
197+
198+
'CREATE TABLE ... AS SELECT' is binlogged as
199+
200+
'CREATE TABLE ... START TRANSACTION'
201+
'TABLE MAP'
202+
'ROW EVENT'
203+
'ROW EVENT'
204+
...
205+
'XID / COMMIT'
206+
207+
At replica, flag is used to identify the 'CREATE TABLE ... START
208+
TRANSACTION' block of 'CREATE TABLE ... AS SELECT' event.
197209
*/
198210
bool is_create_table_as_query_block;
199211
} Trans_param;

sql/rpl_handler.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,9 @@ int Trans_delegate::before_commit(THD *thd, bool all,
576576
param.original_server_version = &(thd->variables.original_server_version);
577577
param.immediate_server_version = &(thd->variables.immediate_server_version);
578578
param.is_create_table_as_query_block =
579-
(thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
580-
!thd->lex->query_block->field_list_is_empty());
579+
((thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
580+
!thd->lex->query_block->field_list_is_empty()) ||
581+
thd->m_transactional_ddl.inited());
581582

582583
bool is_real_trans =
583584
(all || !thd->get_transaction()->is_active(Transaction_ctx::SESSION));

0 commit comments

Comments
 (0)