File: gr_member_join_with_inbound_channel.test

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (197 lines) | stat: -rw-r--r-- 7,627 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
################################################################################
#
# ==== Purpose ====
#
# On a group with an inbound channel on the primary, receiving transactions
# T1, T2 in this order, if T2 is delivered/certified before T1, and a
# View_change occurs between the delivery of T2 and T1, verify that the primary
# bypasses replica-preserve-commit-order and allows T2 to commit before T1.
#
# Footnote:
# The mechanism to bypass replica-preserve-commit-order is necessary in order to
# avoid the following deadlock, which would occur otherwise:
#  1. T2 waits for T1 to commit, because of replica-preserve-commit-order
#  2. T1 waits for the View_change, because transactions delivered/certified
#     after a view_change must also commit after the view_change (using the
#     BGC ticket manager).
#  3. The view change waits for T2, because transactions delivered/certified
#     before a view_change must also commit before the view_change (using the
#     BGC ticket manager)
#
# ==== Requirements ====
#
# Given transactions T1, T2 are delivered in reverse order with a view_change
# between them:
#
# R1. T2 should commit before T1
# R2. T2 should emit an error message
# R3. A transactions following the View_change must respect
#     replica-preserve-commit-order
#
# ==== Test steps ====
#
# 0. The test requires 4 servers:
#    server1: group primary with a inbound channel replicating from server3
#    server2: secondary
#    server3: secondary
#    server4: standalone server
# 1. server1: Bootstrap group.
#    Start an inbound channel that replicates from server4.
# 2. server2: join the group.
# 3. server1: use LOCK TABLES to ensure that T1 will be blocked
# 4. server4: commit T1 and T2
# 5. server1: wait until T2 blocks waiting on commit order
# 6. server3: join the group
# 7. server1: wait until T2 has committed (which it does because the joining
#    server forces it to violate replica-preserve-commit-order).
#    Verify that no transaction blocks waiting for commit order any more.
#    Verify that T1 has not committed yet.
#    Verify that gtid_executed is 1 element smaller on server1 than server4.
#    Verify that there is a warning in the error log.
# 8. server4: commit transaction T3 on table t2.
# 9. server1: wait until T3 blocks waiting for commit order
#    Verify that t2 still contains only one row
#10. server1: UNLOCK TABLES
#    Wait for T2 and T3 to finish
#11. Clean up.
################################################################################

--source include/only_mts_replica_parallel_type_logical_clock.inc
--let $option_name = replica_parallel_workers
--let $option_operator = >
--let $option_value = 1
--source include/only_with_option.inc
--let $group_replication_group_name = aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
--source include/have_group_replication_plugin.inc
--let $rpl_group_replication_single_primary_mode = 1
--let $rpl_skip_group_replication_start = 1
--let $rpl_server_count = 4
--let $rpl_gtid_utils = 1
--source include/group_replication.inc

--let $assert_escape = 1

--echo # Bootstrap group with server1 as primary and server2, server3 as secondaries.
--let $rpl_connection_name = server1
--source include/rpl_connection.inc
--source include/start_and_bootstrap_group_replication.inc

--echo # Create inbound channel from server4 to server1
--replace_result $SERVER_MYPORT_4 SERVER_4_PORT
--eval CHANGE REPLICATION SOURCE TO SOURCE_HOST='127.0.0.1', SOURCE_USER='root', SOURCE_AUTO_POSITION=1, SOURCE_PORT=$SERVER_MYPORT_4 FOR CHANNEL 'ch1'
--let $rpl_channel_name = 'ch1'
--source include/start_slave.inc
--let $rpl_channel_name =

--echo # Create tables
--let $rpl_connection_name = server4
--source include/rpl_connection.inc
CREATE TABLE t1 (c1 INT NOT NULL PRIMARY KEY);
CREATE TABLE t2 (c1 INT NOT NULL PRIMARY KEY);
--let $sync_slave_connection= server1
--source include/sync_slave_sql_with_master.inc

--echo # Make server2 join the group
--let $rpl_connection_name = server2
--source include/rpl_connection.inc
--source include/start_group_replication.inc

--echo # Take a lock on the primary so that T1 will be blocked
--let $rpl_connection_name = server_1_1
--source include/rpl_connection.inc
LOCK TABLES t1 WRITE;

--echo # Commit transaction T1 on table t1, then transaction T2 on t2.
--let $rpl_connection_name = server4
--source include/rpl_connection.inc
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
--let $source_gtid_executed = `SELECT @@global.gtid_executed`

--echo # Wait until T2 is waiting for T1 to commit.
--let $rpl_connection_name = server1
--source include/rpl_connection.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM performance_schema.threads WHERE PROCESSLIST_STATE = 'Waiting for preceding transaction to commit'
--source include/wait_condition.inc

--source include/save_error_log_position.inc

--echo # Join server3 to the group
--let $rpl_connection_name = server3
--source include/rpl_connection.inc
--source include/start_group_replication.inc

--echo # Wait for T2 to commit on server1
--let $rpl_connection_name = server1
--source include/rpl_connection.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t2
--source include/wait_condition.inc

--let $wait_condition = SELECT COUNT(*) = 0 FROM performance_schema.threads WHERE PROCESSLIST_STATE = 'Waiting for preceding transaction to commit'
--source include/wait_condition.inc

--let $error_pattern = The transaction '[a-z0-9\-]*:[0-9]*' will commit out of order with respect to its source to follow the group global order
--source include/assert_error_log.inc

--echo # Verify that t1 is still not committed

--let $assert_text = There should be one missing GTID
--let $assert_cond = [SELECT GTID_COUNT(GTID_SUBTRACT('$source_gtid_executed', @@global.gtid_executed))] = 1
--source include/assert.inc

--let $rpl_connection_name = server_1_1
--source include/rpl_connection.inc
--let $assert_text = t1 should still be empty
--let $assert_cond = [SELECT COUNT(*) FROM test.t1] = 0
--source include/assert.inc

--echo # Check that new transactions block as needed, *not* violating replica-preserve-commit-order
--let $rpl_connection_name = server_4
--source include/rpl_connection.inc
INSERT INTO t2 VALUES (3);

--let $rpl_connection_name = server_1
--source include/rpl_connection.inc

--let $wait_condition = SELECT COUNT(*) = 1 FROM performance_schema.threads WHERE PROCESSLIST_STATE = 'Waiting for preceding transaction to commit'
--source include/wait_condition.inc

--let $assert_text = t2 should still have only one element
--let $assert_cond = [SELECT COUNT(*) FROM test.t2] = 1
--source include/assert.inc

--echo # Unblock T1 and T3 and let them finish
--let $rpl_connection_name = server_1_1
--source include/rpl_connection.inc
UNLOCK TABLES;
--source include/rpl_sync.inc

--echo # Clean up
--let $rpl_connection_name = server4
--source include/rpl_connection.inc
DROP TABLE t1;
DROP TABLE t2;
--let $sync_slave_connection= server1
--source include/sync_slave_sql_with_master.inc

--let $rpl_connection_name = server1
--source include/rpl_connection.inc
--let $rpl_channel_name='ch1'
--source include/stop_slave.inc
--let $rpl_channel_name=
RESET REPLICA ALL FOR CHANNEL 'ch1';
--source include/rpl_sync.inc

--let $rpl_connection_name = server3
--source include/rpl_connection.inc
--source include/stop_group_replication.inc

--let $rpl_connection_name = server2
--source include/rpl_connection.inc
--source include/stop_group_replication.inc

--let $rpl_connection_name = server1
--source include/rpl_connection.inc
--source include/stop_group_replication.inc

--source include/group_replication_end.inc