Skip to content

Commit c4ed1be

Browse files
dr-msanja-byelkin
authored andcommitted
MDEV-21172 Memory leak after failed ADD PRIMARY KEY
1 parent 008ee86 commit c4ed1be

File tree

6 files changed

+78
-23
lines changed

6 files changed

+78
-23
lines changed

mysql-test/suite/innodb/r/instant_alter,4k.rdiff

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,16 @@
119119
connection default;
120120
InnoDB 0 transactions not purged
121121
DROP TABLE t1,t2,t3,t4,big;
122-
@@ -698,7 +712,7 @@
122+
@@ -515,6 +529,8 @@
123+
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
124+
ALTER TABLE t1 ADD d TEXT;
125+
ALTER TABLE t1 ADD PRIMARY KEY (a,b);
126+
+Warnings:
127+
+Warning 139 Row size too large (> 1979). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
128+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
129+
DROP TABLE t1;
130+
CREATE TABLE t1
131+
@@ -703,7 +719,7 @@
123132
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
124133
WHERE name = 'test/t2';
125134
clust_index_size
@@ -128,7 +137,7 @@
128137
connection default;
129138
ROLLBACK;
130139
connection analyze;
131-
@@ -708,7 +722,7 @@
140+
@@ -713,7 +729,7 @@
132141
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
133142
WHERE name = 'test/t2';
134143
clust_index_size
@@ -137,7 +146,7 @@
137146
connection default;
138147
BEGIN;
139148
UPDATE t2 SET d1 = repeat(id, 200);
140-
@@ -719,7 +733,7 @@
149+
@@ -724,7 +740,7 @@
141150
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
142151
WHERE name = 'test/t2';
143152
clust_index_size
@@ -146,7 +155,7 @@
146155
connection default;
147156
ROLLBACK;
148157
connection analyze;
149-
@@ -729,7 +743,7 @@
158+
@@ -734,7 +750,7 @@
150159
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
151160
WHERE name = 'test/t2';
152161
clust_index_size
@@ -155,7 +164,7 @@
155164
connection default;
156165
ALTER TABLE t2 DROP p;
157166
affected rows: 0
158-
@@ -778,7 +792,9 @@
167+
@@ -783,7 +799,9 @@
159168
info: Records: 0 Duplicates: 0 Warnings: 0
160169
ALTER TABLE t3 ADD COLUMN b BLOB NOT NULL;
161170
affected rows: 0
@@ -166,7 +175,7 @@
166175
INSERT INTO t3 SET id=4;
167176
ERROR HY000: Field 'c2' doesn't have a default value
168177
INSERT INTO t3 SET id=4, c2=0, b=0xf09f98b1;
169-
@@ -791,7 +807,9 @@
178+
@@ -796,7 +814,9 @@
170179
ALTER TABLE t3 CHANGE t phrase TEXT DEFAULT 0xc3a4c3a448,
171180
CHANGE b b BLOB NOT NULL DEFAULT 'binary line of business';
172181
affected rows: 4
@@ -177,7 +186,7 @@
177186
INSERT INTO t3 SET id=5, c2=9;
178187
Warnings:
179188
Note 1265 Data truncated for column 'c7' at row 1
180-
@@ -805,7 +823,9 @@
189+
@@ -810,7 +830,9 @@
181190
5 9 POLYGON((1 1,2 2,3 3,1 1)) 1970-01-01 03:00:42 1970-01-01 03:00:42 NULL 03:00:42 1970-01-01 ääH binary line of business
182191
ALTER TABLE t3 DROP c3, DROP c7;
183192
affected rows: 0
@@ -188,7 +197,7 @@
188197
SELECT * FROM t3;
189198
id c2 c4 c5 c6 c8 phrase b
190199
1 1 1970-01-01 03:00:42 1970-01-01 03:00:42 NULL 1970-01-01 The quick brown fox jumps over the lazy dog
191-
@@ -833,6 +853,8 @@
200+
@@ -838,6 +860,8 @@
192201
(id INT PRIMARY KEY, c1 VARCHAR(4000), c2 VARCHAR(4000), c3 VARCHAR(1000),
193202
p POINT NOT NULL DEFAULT ST_GeomFromText('POINT(0 0)'), SPATIAL INDEX(p))
194203
ENGINE=InnoDB ROW_FORMAT=COMPACT;
@@ -197,7 +206,7 @@
197206
BEGIN;
198207
INSERT INTO big
199208
SET id=1, c1=REPEAT('a', 200), c2=REPEAT('b', 200), c3=REPEAT('c', 159);
200-
@@ -850,13 +872,15 @@
209+
@@ -855,13 +879,15 @@
201210
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
202211
WHERE name = 'test/big';
203212
clust_index_size
@@ -215,7 +224,7 @@
215224
CHECKSUM TABLE big;
216225
Table Checksum
217226
test.big 1705165209
218-
@@ -873,7 +897,7 @@
227+
@@ -878,7 +904,7 @@
219228
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
220229
WHERE name = 'test/big';
221230
clust_index_size
@@ -224,7 +233,7 @@
224233
connection default;
225234
ROLLBACK;
226235
CHECKSUM TABLE big;
227-
@@ -886,7 +910,7 @@
236+
@@ -891,7 +917,7 @@
228237
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
229238
WHERE name = 'test/big';
230239
clust_index_size
@@ -233,7 +242,16 @@
233242
connection default;
234243
InnoDB 0 transactions not purged
235244
DROP TABLE t1,t2,t3,t4,big;
236-
@@ -1155,7 +1179,7 @@
245+
@@ -977,6 +1003,8 @@
246+
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
247+
ALTER TABLE t1 ADD d TEXT;
248+
ALTER TABLE t1 ADD PRIMARY KEY (a,b);
249+
+Warnings:
250+
+Warning 139 Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
251+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
252+
DROP TABLE t1;
253+
CREATE TABLE t1
254+
@@ -1165,7 +1193,7 @@
237255
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
238256
WHERE name = 'test/t2';
239257
clust_index_size
@@ -242,7 +260,7 @@
242260
connection default;
243261
ROLLBACK;
244262
connection analyze;
245-
@@ -1165,7 +1189,7 @@
263+
@@ -1175,7 +1203,7 @@
246264
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
247265
WHERE name = 'test/t2';
248266
clust_index_size
@@ -251,7 +269,7 @@
251269
connection default;
252270
BEGIN;
253271
UPDATE t2 SET d1 = repeat(id, 200);
254-
@@ -1176,7 +1200,7 @@
272+
@@ -1186,7 +1214,7 @@
255273
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
256274
WHERE name = 'test/t2';
257275
clust_index_size
@@ -260,7 +278,7 @@
260278
connection default;
261279
ROLLBACK;
262280
connection analyze;
263-
@@ -1186,7 +1210,7 @@
281+
@@ -1196,7 +1224,7 @@
264282
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
265283
WHERE name = 'test/t2';
266284
clust_index_size
@@ -269,7 +287,7 @@
269287
connection default;
270288
ALTER TABLE t2 DROP p;
271289
affected rows: 0
272-
@@ -1307,7 +1331,7 @@
290+
@@ -1317,7 +1345,7 @@
273291
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
274292
WHERE name = 'test/big';
275293
clust_index_size
@@ -278,7 +296,7 @@
278296
connection default;
279297
ALTER TABLE big ADD COLUMN
280298
(d1 INT DEFAULT 0, d2 VARCHAR(20) DEFAULT 'abcde',
281-
@@ -1330,7 +1354,7 @@
299+
@@ -1340,7 +1368,7 @@
282300
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
283301
WHERE name = 'test/big';
284302
clust_index_size
@@ -287,7 +305,7 @@
287305
connection default;
288306
ROLLBACK;
289307
CHECKSUM TABLE big;
290-
@@ -1343,7 +1367,7 @@
308+
@@ -1353,7 +1381,7 @@
291309
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
292310
WHERE name = 'test/big';
293311
clust_index_size
@@ -296,10 +314,10 @@
296314
connection default;
297315
InnoDB 0 transactions not purged
298316
DROP TABLE t1,t2,t3,t4,big;
299-
@@ -1431,5 +1455,5 @@
317+
@@ -1446,5 +1474,5 @@
300318
FROM information_schema.global_status
301319
WHERE variable_name = 'innodb_instant_alter_column';
302320
instants
303-
-54
304-
+55
321+
-57
322+
+58
305323
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;

mysql-test/suite/innodb/r/instant_alter.result

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,13 @@ CHECK TABLE t1;
512512
Table Op Msg_type Msg_text
513513
test.t1 check status OK
514514
DROP TABLE t1;
515+
SET innodb_strict_mode = ON;
516+
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
517+
ALTER TABLE t1 ADD d TEXT;
518+
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
519+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
520+
DROP TABLE t1;
521+
SET innodb_strict_mode = OFF;
515522
CREATE TABLE t1
516523
(id INT PRIMARY KEY, c2 INT UNIQUE,
517524
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -969,6 +976,13 @@ CHECK TABLE t1;
969976
Table Op Msg_type Msg_text
970977
test.t1 check status OK
971978
DROP TABLE t1;
979+
SET innodb_strict_mode = ON;
980+
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
981+
ALTER TABLE t1 ADD d TEXT;
982+
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
983+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
984+
DROP TABLE t1;
985+
SET innodb_strict_mode = OFF;
972986
CREATE TABLE t1
973987
(id INT PRIMARY KEY, c2 INT UNIQUE,
974988
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1426,10 +1440,17 @@ CHECK TABLE t1;
14261440
Table Op Msg_type Msg_text
14271441
test.t1 check status OK
14281442
DROP TABLE t1;
1443+
SET innodb_strict_mode = ON;
1444+
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
1445+
ALTER TABLE t1 ADD d TEXT;
1446+
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
1447+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
1448+
DROP TABLE t1;
1449+
SET innodb_strict_mode = OFF;
14291450
disconnect analyze;
14301451
SELECT variable_value-@old_instant instants
14311452
FROM information_schema.global_status
14321453
WHERE variable_name = 'innodb_instant_alter_column';
14331454
instants
1434-
54
1455+
57
14351456
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;

mysql-test/suite/innodb/r/instant_alter_bugs.result

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,4 @@ DROP FOREIGN KEY fk1,
169169
CHANGE b d INT UNSIGNED,
170170
ADD c INT;
171171
DROP TABLE t2, t1;
172+
# End of 10.3 tests

mysql-test/suite/innodb/t/instant_alter.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,18 @@ DELETE FROM t1;
396396
CHECK TABLE t1;
397397
DROP TABLE t1;
398398

399+
# MDEV-21172 Memory leak during ADD PRIMARY KEY
400+
401+
SET innodb_strict_mode = ON;
402+
eval CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) $engine;
403+
ALTER TABLE t1 ADD d TEXT;
404+
--error 0,ER_TOO_BIG_ROWSIZE
405+
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
406+
# Exploit MDEV-17468 to force the table definition to be reloaded
407+
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
408+
DROP TABLE t1;
409+
SET innodb_strict_mode = OFF;
410+
399411
dec $format;
400412
let $redundant_4k= 0;
401413
}

mysql-test/suite/innodb/t/instant_alter_bugs.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,5 @@ ALTER TABLE t2
169169
CHANGE b d INT UNSIGNED,
170170
ADD c INT;
171171
DROP TABLE t2, t1;
172+
173+
--echo # End of 10.3 tests

storage/innobase/handler/handler0alter.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5541,6 +5541,7 @@ prepare_inplace_alter_table_dict(
55415541
if (index) {
55425542
dict_mem_index_free(index);
55435543
}
5544+
error_handling_drop_uncached_1:
55445545
while (++a < ctx->num_to_add_index) {
55455546
dict_mem_index_free(ctx->add_index[a]);
55465547
}
@@ -5552,7 +5553,7 @@ prepare_inplace_alter_table_dict(
55525553
ctx->add_index[a] = index;
55535554
if (!info.row_size_is_acceptable(*index)) {
55545555
error = DB_TOO_BIG_RECORD;
5555-
goto error_handling;
5556+
goto error_handling_drop_uncached_1;
55565557
}
55575558
index->parser = index_defs[a].parser;
55585559
index->has_new_v_col = has_new_v_col;

0 commit comments

Comments
 (0)