File: rpl_gtid_drop_table.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 (338 lines) | stat: -rw-r--r-- 15,204 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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# ==== Purpose ====
#
# In order to avoid problems with GTIDs, MySQL server should refuse to execute
# any statements that will be split before sending to binlog if
# @@SESSION.GTID_NEXT is set to 'UUID:NUMBER'.
#
# In MySQL server, DROP TABLE statements can be split into up to three
# distinct binlog events: one containing the regular tables, one containing
# transactional temporary tables and one containing non-transactional
# temporary tables.
#
# In the first part, this test will verify if a splittable DROP TABLE
# statement is being refused to execute throwing the correct error to the
# client session.
#
# In the second part, this test will verify an issue with inexistent temporary
# tables being assumed as transactional on the slave side. This was making
# the slave to split a DROP statement that the master logged as a single DROP
# statement.
#
# In the third part, this test will verify that a slave having to drop
# temporary tables because of the master have restarted will split the DROP
# TABLE statement also based on table types (transactional or not).
#
# The details about the implementation of this test is in the beginning of
# each part.
#
# ==== Related Bugs and Worklogs ====
#
# BUG#17620053: SET GTID_NEXT AND DROP TABLE WITH BOTH REGULAR AND TEMPORARY
#               TABLES
#
--let $rpl_topology= 1->2->3
--source include/rpl_init.inc
--source include/rpl_default_connections.inc
--source include/have_myisam.inc

--echo #
--echo # First part
--echo #
#
# This part verifies the splittable DROP TABLE behavior in client sessions by
# creating three tables (one regular and two temporary), setting session
# GTID_NEXT to a specific GTID and then trying to issue a DROP TABLE
# statement containing the combinations of at least two tables.
#
# This part only applies to statement binary log format, as otherwise temporary
# table operations are completely invisible to the binary log.
#
# As DROP statements with both regular and temporary tables or with
# transactional and non transactional temporary tables are split before
# sending to binlog, the following DROP statements must return an error to the
# client session because of being considered unsafe for GTID enforcement as it
# would be split into two (or three) statements to be sent to binlog.
#
# In order to improve the test coverage, we will verify DROP TABLE statements
# with all combinations of the following:
# 1) Regular transactional table;
# 2) Regular non-transactional table;
# 3) Temporary transactional table;
# 4) Temporary non-transactional table;
# 5) Nonexistent table.
#
# With the above set we could make up to 32 possibilities (including none of
# above). But we will test the behavior only for the following combinations:
# - 18 error cases (ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID):
#   (1 | 2 | 1+2) + (3 | 4 | 3+4) + (nothing | 5)
#   (3+4) | (3+4+5)
#   (3 | 4) + 5  /* as this it not DROP TEMPORARY, nonexistent tables will be
#                   assumed as regular tables, so the DROP will be split */
# - 3 error cases (ER_BAD_TABLE_ERROR):
#   (1 | 2 | 1+2) + 5
# - 1 non-error case:
#   1+2
# Note: for ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID cases, the
# statement will not be executed and no DROP will be performed. For
# ER_BAD_TABLE_ERROR cases, the existent tables will be dropped regardless the
# error.

# Create two regular tables and two temporary tables with distinct storage engines
--source include/rpl_connection_master.inc
CREATE TABLE trans_t1 (c1 INT) ENGINE=InnoDB;
CREATE TABLE non_trans_t1 (c1 INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE temp_trans_t1 (c1 INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trans_t1 (c1 INT) ENGINE=MyISAM;

--let $binlog_format= `SELECT @@GLOBAL.binlog_format`
if ($binlog_format == "STATEMENT")
{
  --echo # Error cases ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID
  --let $next_gtid= '11111111-1111-1111-1111-111111111111:1'
  --let $expected_error= ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID
  # reg trans + reg non trans + temp trans
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + reg non trans + temp trans + temp non trans
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + reg non trans + temp trans + temp non trans + inexistent
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + reg non trans + temp trans + inexistent
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + reg non trans + temp non trans
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + reg non trans + temp non trans + inexistent
  --let $statement= DROP TABLE trans_t1, non_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp trans
  --let $statement= DROP TABLE trans_t1, temp_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp trans + temp non trans
  --let $statement= DROP TABLE trans_t1, temp_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp trans + temp non trans + inexistent
  --let $statement= DROP TABLE trans_t1, temp_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp trans + inexistent
  --let $statement= DROP TABLE trans_t1, temp_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp non trans
  --let $statement= DROP TABLE trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg trans + temp non trans + inexistent
  --let $statement= DROP TABLE trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp trans
  --let $statement= DROP TABLE non_trans_t1, temp_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp trans + temp non trans
  --let $statement= DROP TABLE non_trans_t1, temp_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp trans + temp non trans + inexistent
  --let $statement= DROP TABLE non_trans_t1, temp_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp trans + inexistent
  --let $statement= DROP TABLE non_trans_t1, temp_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp non trans
  --let $statement= DROP TABLE non_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # reg non trans + temp non trans + inexistent
  --let $statement= DROP TABLE non_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # temp trans + temp non trans
  --let $statement= DROP TABLE temp_trans_t1, temp_non_trans_t1
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # temp trans + temp non trans + inexistent
  --let $statement= DROP TABLE temp_trans_t1, temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # temp trans + inexistent
  --let $statement= DROP TABLE temp_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
  # temp non trans + inexistent
  --let $statement= DROP TABLE temp_non_trans_t1, non_existent
  --source extra/rpl_tests/rpl_gtid_drop_table.inc
}

--echo # Error cases ER_BAD_TABLE_ERROR.
# All error cases below are no-ops.
--let $expected_error= ER_BAD_TABLE_ERROR

# reg trans + reg non trans + inexistent
--let $next_gtid= '11111111-1111-1111-1111-111111111111:1'
--let $statement= DROP TABLE trans_t1, non_trans_t1, non_existent
--source extra/rpl_tests/rpl_gtid_drop_table.inc
# reg trans + inexistent
--let $next_gtid= '11111111-1111-1111-1111-111111111111:2'
--let $statement= DROP TABLE trans_t1, non_existent
--source extra/rpl_tests/rpl_gtid_drop_table.inc
# reg non trans + inexistent
--let $next_gtid= '11111111-1111-1111-1111-111111111111:3'
--let $statement= DROP TABLE non_trans_t1, non_existent
--source extra/rpl_tests/rpl_gtid_drop_table.inc

--echo # Non-error cases
--let $expected_error=

# reg trans + reg non trans
--let $next_gtid= '11111111-1111-1111-1111-111111111111:4'
--let $statement= DROP TABLE trans_t1, non_trans_t1
--source extra/rpl_tests/rpl_gtid_drop_table.inc

SET GTID_NEXT= AUTOMATIC;
CREATE TABLE trans_t1 (c1 INT) ENGINE=InnoDB;


--echo #
--echo # Second part
--echo #
#
# The MySQL server cannot evaluate if an inexistent temporary table is
# transactional or not. Before the fix for BUG#17620053, the inexistent
# temporary tables were assumed to be transactional.
#
# This assumption could lead to a split if, for example, you issue a DROP
# TEMPORARY TABLE for two existent non-transactional temporary tables in the
# master (will binlog only one statement) but a filter made one of the
# temporary tables inexistent on the slave side (will binlog two statements:
# one with the existent non-transactional table and other with the inexistent
# table assumed to be transactional).
#
# As this test has a filter in its slave configuration like this:
# '--replicate-ignore-table=test.temp_ignore', all statements containing the
# 'test.temp_ignore' temporary table alone wont be executed by the SQL slave
# thread. So, the CREATE TABLE statements for 'temp_ignore' table will be
# executed only on the master.
#
# Issuing a DROP TEMPORARY TABLE statement in the master containing the two
# non-transaction temporary tables would result in a single binlog statement,
# as the two tables are non-transactional ones.
#
# In the slave, because of the filter, the non-replicated table will be
# assumed unknown. With the fix for BUG#17620053, the unknown tables will
# be assumed as transactional only if at least one transactional table is
# dropped. If the DROP recognizes only non-transactional tables, the unknown
# temporary tables will be assumed non-transactional, avoiding splitting the
# statement.

# Create an additional non-transactional temporary table that will not be
# replicated due to the replication filter, only t1 will be replicated.
CREATE TEMPORARY TABLE temp_ignore (c1 INT) ENGINE=MyISAM;
# Drop the two non-transactional temp tables
DROP TEMPORARY TABLE IF EXISTS temp_ignore, temp_non_trans_t1;
# Sync to know that everything was replicated
--source include/sync_slave_sql_with_master.inc
# Back to the 'master' connection
--source include/rpl_connection_master.inc
# Create temp_ignore table again, but with InnoDB storage engine
CREATE TEMPORARY TABLE temp_ignore (c1 INT) ENGINE=InnoDB;
# Drop the two transactional temp tables
DROP TEMPORARY TABLE IF EXISTS temp_ignore, temp_trans_t1;
# Sync to know that everything was replicated
--source include/sync_slave_sql_with_master.inc

--echo #
--echo # Third part
--echo #
#
# This part was adapted from rpl_create_drop_temp_table.test
#
# As we use three server topology, when the slave (mysqld 2) detects the
# master (mysqld 1) has restarted it will drop the temporary tables and
# will binlog the DROP TABLE statements that will be replicated to
# the third server (mysqld 3).
#
# As the DROP of temporary table in the slave side groups the tables
# by pseudo-threadid and by database, we will use two sessions on master,
# creating three sets of temporary tables, each set on a distinct database.
#
# The first set contains two tables with distinct storage engines, the
# second set contains a single table and the third set contains two tables
# with the same storage engine.
#
--source include/rpl_connection_master.inc
SET SESSION sql_log_bin= 0;
call mtr.add_suppression("Error: table .* does not exist in the InnoDB internal");
SET SESSION sql_log_bin= 1;

CREATE DATABASE test2;
CREATE DATABASE test3;

# Create two temporary tables with distinct storage engines in 'test'
# This should generate two DROP statements
use test;
CREATE TEMPORARY TABLE temp_trans_t1 (c1 INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trans_t1 (c1 INT) ENGINE=MyISAM;
# Create one temporary table with transactional storage engine in 'test2'
# This should generate only one DROP statement
USE test2;
CREATE TEMPORARY TABLE temp_trans_t1 (c1 INT) ENGINE=InnoDB;
# Create two temporary tables with transactional storage engine in 'test3'
# This should generate only one DROP statement with the two tables
USE test3;
CREATE TEMPORARY TABLE temp_trans_t1 (c1 INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_trans_t2 (c1 INT) ENGINE=InnoDB;

# Create two temporary tables with distinct storage engines in 'test'
# in another client session. This should generate two DROP statements
--source include/rpl_connection_master1.inc
use test;
CREATE TEMPORARY TABLE temp_trans_t1 (c1 INT) ENGINE=InnoDB;
CREATE TEMPORARY TABLE temp_non_trans_t1 (c1 INT) ENGINE=MyISAM;
# Create one temporary table with non-transactional storage engine in 'test2'
# This should generate only one DROP statement
USE test2;
CREATE TEMPORARY TABLE temp_non_trans_t1 (c1 INT) ENGINE=MyISAM;
# Create two temporary tables with non-transactional storage engine in 'test3'
# This should generate only one DROP statement with the two tables
USE test3;
CREATE TEMPORARY TABLE temp_non_trans_t1 (c1 INT) ENGINE=MyISAM;
CREATE TEMPORARY TABLE temp_non_trans_t2 (c1 INT) ENGINE=MyISAM;

# Sync to know that everything was replicated
--source include/sync_slave_sql_with_master.inc

# Stop slave io thread
--disable_warnings
--source include/stop_slave_io.inc
--enable_warnings

# Kill Master so that it does not go through THD::cleanup logic. Hence it does
# not generate "drop temporary" query for 'temp' tables.
--let $rpl_server_number= 1
--let $rpl_force_stop=1
--source include/rpl_stop_server.inc

# Restart Master (generates Format Description event which tells slave to
# drop all temporary tables)
--source include/rpl_start_server.inc

# Start and sync slave IO thread
--source include/rpl_connection_slave.inc
--source include/start_slave_io.inc
--source include/rpl_connection_master.inc
--source include/sync_slave_io_with_master.inc

# Wait for slave thread to apply all events (including the newly generated
# FormatDescription event which tells slave SQL thread to drop all temporary
--let $show_statement= SHOW PROCESSLIST
--let $field= State
--let $condition= 'Replica has read all relay log; waiting for the slave I/O thread to update it';
--source include/wait_show_condition.inc

# Now we verify replica_open_temp_tables, it should be '0'
--let $assert_text= Replica_open_temp_tables should be 0
--let $assert_cond= [SHOW STATUS LIKE "Replica_open_temp_tables", Value, 1] = 0
--source include/assert.inc

# Cleanup replication
--source include/rpl_connection_master.inc
USE test;
DROP TABLE trans_t1;
DROP DATABASE test2;
DROP DATABASE test3;
--source include/rpl_end.inc