@@ -97,5 +97,290 @@ set use_stat_tables=default;
97
97
set histogram_type=default;
98
98
set histogram_size=default;
99
99
#
100
+ # MDEV-31957 Concurrent ALTER and ANALYZE collecting statistics can
101
+ # result in stale statistical data
102
+ #
103
+ CREATE TABLE t1 (a INT, b VARCHAR(128));
104
+ INSERT INTO t1 SELECT seq, CONCAT('s',seq) FROM seq_1_to_100;
105
+ connect con1,localhost,root,,;
106
+ ALTER TABLE t1 MODIFY b BLOB;
107
+ connection default;
108
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
109
+ connection con1;
110
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
111
+ connection default;
112
+ disconnect con1;
113
+ select db_name,table_name,column_name from mysql.column_stats;
114
+ db_name table_name column_name
115
+ test t1 a
116
+ drop table t1;
117
+ #
118
+ # Testing swapping columns
119
+ #
120
+ create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=innodb;
121
+ insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100;
122
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
123
+ Table Op Msg_type Msg_text
124
+ test.t1 analyze status Engine-independent statistics collected
125
+ test.t1 analyze status OK
126
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
127
+ db_name table_name column_name avg_length
128
+ test t1 a 4.0000
129
+ test t1 b 50.5000
130
+ test t1 c 2.0000
131
+ test t1 d 4.5000
132
+ alter table t1 change b c varchar(200), change c b varchar(200);
133
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
134
+ db_name table_name column_name avg_length
135
+ test t1 a 4.0000
136
+ test t1 b 2.0000
137
+ test t1 c 50.5000
138
+ test t1 d 4.5000
139
+ alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ;
140
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
141
+ db_name table_name column_name avg_length
142
+ test t1 a 4.0000
143
+ test t1 b 4.5000
144
+ test t1 c 2.0000
145
+ test t1 d 50.5000
146
+ alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ;
147
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
148
+ db_name table_name column_name avg_length
149
+ test t1 a 4.0000
150
+ test t1 c 4.5000
151
+ test t1 d 2.0000
152
+ test t1 e 50.5000
153
+ alter table t1 change e d varchar(200), drop column d;
154
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
155
+ db_name table_name column_name avg_length
156
+ test t1 a 4.0000
157
+ test t1 c 4.5000
158
+ test t1 d 50.5000
159
+ # Test having non existing column in column_stats
160
+ insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1","b");
161
+ alter table t1 change c d varchar(200), change d b varchar(200);
162
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
163
+ db_name table_name column_name avg_length
164
+ test t1 a 4.0000
165
+ test t1 b 50.5000
166
+ test t1 d 4.5000
167
+ # Test having a conflicting temporary name
168
+ insert into mysql.column_stats (db_name,table_name,column_name) values ("test","t1",concat("#sql_tmp_name#1",char(0)));
169
+ alter table t1 change d b varchar(200), change b d varchar(200);
170
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
171
+ db_name table_name column_name avg_length
172
+ test t1 a 4.0000
173
+ test t1 b 4.5000
174
+ test t1 d 50.5000
175
+ drop table t1;
176
+ truncate table mysql.column_stats;
177
+ create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100)) engine=myisam;
178
+ insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100;
179
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
180
+ Table Op Msg_type Msg_text
181
+ test.t1 analyze status Engine-independent statistics collected
182
+ test.t1 analyze status OK
183
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
184
+ db_name table_name column_name avg_length
185
+ test t1 a 4.0000
186
+ test t1 b 50.5000
187
+ test t1 c 2.0000
188
+ test t1 d 4.5000
189
+ alter table t1 change b c varchar(200), change c b varchar(200);
190
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
191
+ db_name table_name column_name avg_length
192
+ test t1 a 4.0000
193
+ test t1 d 4.5000
194
+ analyze table t1 persistent for columns(b,c) indexes all;
195
+ Table Op Msg_type Msg_text
196
+ test.t1 analyze status Engine-independent statistics collected
197
+ test.t1 analyze status Table is already up to date
198
+ alter table t1 change b c varchar(200), change c d varchar(200), change d b varchar(200) ;
199
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
200
+ db_name table_name column_name avg_length
201
+ test t1 a 4.0000
202
+ test t1 b 50.5000
203
+ test t1 c 2.0000
204
+ analyze table t1 persistent for columns(d) indexes all;
205
+ Table Op Msg_type Msg_text
206
+ test.t1 analyze status Engine-independent statistics collected
207
+ test.t1 analyze status Table is already up to date
208
+ alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ;
209
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
210
+ db_name table_name column_name avg_length
211
+ test t1 a 4.0000
212
+ test t1 c 50.5000
213
+ test t1 d 2.0000
214
+ test t1 e 50.5000
215
+ alter table t1 change e d varchar(200), drop column d;
216
+ select db_name,table_name,column_name,avg_length from mysql.column_stats order by column_name;
217
+ db_name table_name column_name avg_length
218
+ test t1 a 4.0000
219
+ test t1 c 50.5000
220
+ test t1 d 50.5000
221
+ drop table t1;
222
+ truncate table mysql.column_stats;
223
+ create table t1 (a int, b blob, unique(b)) engine= innodb;
224
+ analyze table t1 persistent for all;
225
+ Table Op Msg_type Msg_text
226
+ test.t1 analyze status Engine-independent statistics collected
227
+ test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
228
+ test.t1 analyze status OK
229
+ select column_name from mysql.column_stats where table_name = 't1';
230
+ column_name
231
+ a
232
+ drop table t1;
233
+ create table t1 (a int, b blob, c int generated always as (length(b)) virtual) engine= innodb;
234
+ analyze table t1 persistent for all;
235
+ Table Op Msg_type Msg_text
236
+ test.t1 analyze status Engine-independent statistics collected
237
+ test.t1 analyze Warning Engine-independent statistics are not collected for column 'b'
238
+ test.t1 analyze status OK
239
+ select column_name from mysql.column_stats where table_name = 't1';
240
+ column_name
241
+ a
242
+ c
243
+ drop table t1;
244
+ CREATE or replace TABLE t1 (a INT, b CHAR(8));
245
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
246
+ Table Op Msg_type Msg_text
247
+ test.t1 analyze status Engine-independent statistics collected
248
+ test.t1 analyze status Table is already up to date
249
+ ALTER TABLE t1 CHANGE b c INT, ORDER BY b;
250
+ SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1';
251
+ db_name table_name column_name
252
+ test t1 a
253
+ test t1 c
254
+ drop table t1;
255
+ CREATE or replace TABLE t1 (a INT, b CHAR(8));
256
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
257
+ Table Op Msg_type Msg_text
258
+ test.t1 analyze status Engine-independent statistics collected
259
+ test.t1 analyze status Table is already up to date
260
+ ALTER TABLE t1 RENAME COLUMN b to c, ALGORITHM=COPY;
261
+ SELECT db_name, table_name, column_name FROM mysql.column_stats where table_name = 't1';
262
+ db_name table_name column_name
263
+ test t1 a
264
+ test t1 c
265
+ drop table t1;
266
+ #
267
+ # Testing swapping indexes
268
+ #
269
+ create or replace table t1 (a int primary key, b varchar(100), c varchar(100), d varchar(100), index (b), index(c), index(d,b)) engine=innodb;
270
+ insert into t1 select seq, repeat('b',seq),repeat('c',mod(seq,5)), repeat('d',mod(seq,10)) from seq_1_to_100;
271
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
272
+ Table Op Msg_type Msg_text
273
+ test.t1 analyze status Engine-independent statistics collected
274
+ test.t1 analyze status OK
275
+ select * from mysql.index_stats order by index_name, prefix_arity;
276
+ db_name table_name index_name prefix_arity avg_frequency
277
+ test t1 PRIMARY 1 1.0000
278
+ test t1 b 1 1.0000
279
+ test t1 b 2 1.0000
280
+ test t1 c 1 20.0000
281
+ test t1 c 2 1.0000
282
+ test t1 d 1 10.0000
283
+ test t1 d 2 1.0000
284
+ test t1 d 3 1.0000
285
+ alter table t1 rename index b to c, rename index c to d, rename index d to b;
286
+ select * from mysql.index_stats order by index_name;
287
+ db_name table_name index_name prefix_arity avg_frequency
288
+ test t1 PRIMARY 1 1.0000
289
+ test t1 b 1 10.0000
290
+ test t1 b 2 1.0000
291
+ test t1 b 3 1.0000
292
+ test t1 c 1 1.0000
293
+ test t1 c 2 1.0000
294
+ test t1 d 1 20.0000
295
+ test t1 d 2 1.0000
296
+ alter table t1 rename index b to c, rename index c to d, rename index d to e;
297
+ select * from mysql.index_stats order by index_name, prefix_arity;
298
+ db_name table_name index_name prefix_arity avg_frequency
299
+ test t1 PRIMARY 1 1.0000
300
+ test t1 c 1 10.0000
301
+ test t1 c 2 1.0000
302
+ test t1 c 3 1.0000
303
+ test t1 d 1 1.0000
304
+ test t1 d 2 1.0000
305
+ test t1 e 1 20.0000
306
+ test t1 e 2 1.0000
307
+ alter table t1 rename index e to b;
308
+ alter table t1 change b c varchar(200), change c d varchar(200), change d e varchar(200) ;
309
+ show create table t1;
310
+ Table Create Table
311
+ t1 CREATE TABLE `t1` (
312
+ `a` int(11) NOT NULL,
313
+ `c` varchar(200) DEFAULT NULL,
314
+ `d` varchar(200) DEFAULT NULL,
315
+ `e` varchar(200) DEFAULT NULL,
316
+ PRIMARY KEY (`a`),
317
+ KEY `d` (`c`),
318
+ KEY `b` (`d`),
319
+ KEY `c` (`e`,`c`)
320
+ ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
321
+ select * from mysql.index_stats order by index_name, prefix_arity;
322
+ db_name table_name index_name prefix_arity avg_frequency
323
+ test t1 PRIMARY 1 1.0000
324
+ test t1 b 1 20.0000
325
+ test t1 b 2 1.0000
326
+ test t1 c 1 10.0000
327
+ test t1 c 2 1.0000
328
+ test t1 c 3 1.0000
329
+ test t1 d 1 1.0000
330
+ test t1 d 2 1.0000
331
+ # Test having a conflicting temporary name
332
+ insert into mysql.index_stats (db_name,table_name,index_name,prefix_arity) values ("test","t1",concat("#sql_tmp_name#1",char(0)),1);
333
+ alter table t1 rename index c to d, rename index d to c;
334
+ select * from mysql.index_stats order by index_name, prefix_arity;
335
+ db_name table_name index_name prefix_arity avg_frequency
336
+ test t1 PRIMARY 1 1.0000
337
+ test t1 b 1 20.0000
338
+ test t1 b 2 1.0000
339
+ test t1 c 1 1.0000
340
+ test t1 c 2 1.0000
341
+ test t1 d 1 10.0000
342
+ test t1 d 2 1.0000
343
+ test t1 d 3 1.0000
344
+ drop table t1;
345
+ select * from mysql.index_stats order by index_name, prefix_arity;
346
+ db_name table_name index_name prefix_arity avg_frequency
347
+ #
348
+ # Test of adding key that replaces foreign key
349
+ #
350
+ CREATE TABLE t1 (aaaa INT, b INT, KEY(b), FOREIGN KEY(aaaa) REFERENCES t1(b)) ENGINE=InnoDB;
351
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
352
+ Table Op Msg_type Msg_text
353
+ test.t1 analyze status Engine-independent statistics collected
354
+ test.t1 analyze status OK
355
+ SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name;
356
+ index_name
357
+ aaaa
358
+ b
359
+ ALTER TABLE t1 ADD KEY idx(aaaa);
360
+ SHOW CREATE TABLE t1;
361
+ Table Create Table
362
+ t1 CREATE TABLE `t1` (
363
+ `aaaa` int(11) DEFAULT NULL,
364
+ `b` int(11) DEFAULT NULL,
365
+ KEY `b` (`b`),
366
+ KEY `idx` (`aaaa`),
367
+ CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`aaaa`) REFERENCES `t1` (`b`)
368
+ ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
369
+ SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name;
370
+ index_name
371
+ b
372
+ truncate table mysql.index_stats;
373
+ ANALYZE TABLE t1 PERSISTENT FOR ALL;
374
+ Table Op Msg_type Msg_text
375
+ test.t1 analyze status Engine-independent statistics collected
376
+ test.t1 analyze status OK
377
+ SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name;
378
+ index_name
379
+ b
380
+ idx
381
+ ALTER TABLE t1 DROP KEY idx;
382
+ ERROR HY000: Cannot drop index 'idx': needed in a foreign key constraint
383
+ DROP TABLE t1;
384
+ #
100
385
# End of 10.6 tests
101
386
#
0 commit comments