Commit c4ed1bee authored by Marko Mäkelä's avatar Marko Mäkelä Committed by Oleksandr Byelkin

MDEV-21172 Memory leak after failed ADD PRIMARY KEY

parent 008ee867
...@@ -119,7 +119,16 @@ ...@@ -119,7 +119,16 @@
connection default; connection default;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged
DROP TABLE t1,t2,t3,t4,big; DROP TABLE t1,t2,t3,t4,big;
@@ -698,7 +712,7 @@ @@ -515,6 +529,8 @@
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 ADD d TEXT;
ALTER TABLE t1 ADD PRIMARY KEY (a,b);
+Warnings:
+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.
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
CREATE TABLE t1
@@ -703,7 +719,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -128,7 +137,7 @@ ...@@ -128,7 +137,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
connection analyze; connection analyze;
@@ -708,7 +722,7 @@ @@ -713,7 +729,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -137,7 +146,7 @@ ...@@ -137,7 +146,7 @@
connection default; connection default;
BEGIN; BEGIN;
UPDATE t2 SET d1 = repeat(id, 200); UPDATE t2 SET d1 = repeat(id, 200);
@@ -719,7 +733,7 @@ @@ -724,7 +740,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -146,7 +155,7 @@ ...@@ -146,7 +155,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
connection analyze; connection analyze;
@@ -729,7 +743,7 @@ @@ -734,7 +750,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -155,7 +164,7 @@ ...@@ -155,7 +164,7 @@
connection default; connection default;
ALTER TABLE t2 DROP p; ALTER TABLE t2 DROP p;
affected rows: 0 affected rows: 0
@@ -778,7 +792,9 @@ @@ -783,7 +799,9 @@
info: Records: 0 Duplicates: 0 Warnings: 0 info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE t3 ADD COLUMN b BLOB NOT NULL; ALTER TABLE t3 ADD COLUMN b BLOB NOT NULL;
affected rows: 0 affected rows: 0
...@@ -166,7 +175,7 @@ ...@@ -166,7 +175,7 @@
INSERT INTO t3 SET id=4; INSERT INTO t3 SET id=4;
ERROR HY000: Field 'c2' doesn't have a default value ERROR HY000: Field 'c2' doesn't have a default value
INSERT INTO t3 SET id=4, c2=0, b=0xf09f98b1; INSERT INTO t3 SET id=4, c2=0, b=0xf09f98b1;
@@ -791,7 +807,9 @@ @@ -796,7 +814,9 @@
ALTER TABLE t3 CHANGE t phrase TEXT DEFAULT 0xc3a4c3a448, ALTER TABLE t3 CHANGE t phrase TEXT DEFAULT 0xc3a4c3a448,
CHANGE b b BLOB NOT NULL DEFAULT 'binary line of business'; CHANGE b b BLOB NOT NULL DEFAULT 'binary line of business';
affected rows: 4 affected rows: 4
...@@ -177,7 +186,7 @@ ...@@ -177,7 +186,7 @@
INSERT INTO t3 SET id=5, c2=9; INSERT INTO t3 SET id=5, c2=9;
Warnings: Warnings:
Note 1265 Data truncated for column 'c7' at row 1 Note 1265 Data truncated for column 'c7' at row 1
@@ -805,7 +823,9 @@ @@ -810,7 +830,9 @@
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 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
ALTER TABLE t3 DROP c3, DROP c7; ALTER TABLE t3 DROP c3, DROP c7;
affected rows: 0 affected rows: 0
...@@ -188,7 +197,7 @@ ...@@ -188,7 +197,7 @@
SELECT * FROM t3; SELECT * FROM t3;
id c2 c4 c5 c6 c8 phrase b id c2 c4 c5 c6 c8 phrase b
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 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
@@ -833,6 +853,8 @@ @@ -838,6 +860,8 @@
(id INT PRIMARY KEY, c1 VARCHAR(4000), c2 VARCHAR(4000), c3 VARCHAR(1000), (id INT PRIMARY KEY, c1 VARCHAR(4000), c2 VARCHAR(4000), c3 VARCHAR(1000),
p POINT NOT NULL DEFAULT ST_GeomFromText('POINT(0 0)'), SPATIAL INDEX(p)) p POINT NOT NULL DEFAULT ST_GeomFromText('POINT(0 0)'), SPATIAL INDEX(p))
ENGINE=InnoDB ROW_FORMAT=COMPACT; ENGINE=InnoDB ROW_FORMAT=COMPACT;
...@@ -197,7 +206,7 @@ ...@@ -197,7 +206,7 @@
BEGIN; BEGIN;
INSERT INTO big INSERT INTO big
SET id=1, c1=REPEAT('a', 200), c2=REPEAT('b', 200), c3=REPEAT('c', 159); SET id=1, c1=REPEAT('a', 200), c2=REPEAT('b', 200), c3=REPEAT('c', 159);
@@ -850,13 +872,15 @@ @@ -855,13 +879,15 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -215,7 +224,7 @@ ...@@ -215,7 +224,7 @@
CHECKSUM TABLE big; CHECKSUM TABLE big;
Table Checksum Table Checksum
test.big 1705165209 test.big 1705165209
@@ -873,7 +897,7 @@ @@ -878,7 +904,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -224,7 +233,7 @@ ...@@ -224,7 +233,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
CHECKSUM TABLE big; CHECKSUM TABLE big;
@@ -886,7 +910,7 @@ @@ -891,7 +917,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -233,7 +242,16 @@ ...@@ -233,7 +242,16 @@
connection default; connection default;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged
DROP TABLE t1,t2,t3,t4,big; DROP TABLE t1,t2,t3,t4,big;
@@ -1155,7 +1179,7 @@ @@ -977,6 +1003,8 @@
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 ADD d TEXT;
ALTER TABLE t1 ADD PRIMARY KEY (a,b);
+Warnings:
+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.
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
CREATE TABLE t1
@@ -1165,7 +1193,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -242,7 +260,7 @@ ...@@ -242,7 +260,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
connection analyze; connection analyze;
@@ -1165,7 +1189,7 @@ @@ -1175,7 +1203,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -251,7 +269,7 @@ ...@@ -251,7 +269,7 @@
connection default; connection default;
BEGIN; BEGIN;
UPDATE t2 SET d1 = repeat(id, 200); UPDATE t2 SET d1 = repeat(id, 200);
@@ -1176,7 +1200,7 @@ @@ -1186,7 +1214,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -260,7 +278,7 @@ ...@@ -260,7 +278,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
connection analyze; connection analyze;
@@ -1186,7 +1210,7 @@ @@ -1196,7 +1224,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2'; WHERE name = 'test/t2';
clust_index_size clust_index_size
...@@ -269,7 +287,7 @@ ...@@ -269,7 +287,7 @@
connection default; connection default;
ALTER TABLE t2 DROP p; ALTER TABLE t2 DROP p;
affected rows: 0 affected rows: 0
@@ -1307,7 +1331,7 @@ @@ -1317,7 +1345,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -278,7 +296,7 @@ ...@@ -278,7 +296,7 @@
connection default; connection default;
ALTER TABLE big ADD COLUMN ALTER TABLE big ADD COLUMN
(d1 INT DEFAULT 0, d2 VARCHAR(20) DEFAULT 'abcde', (d1 INT DEFAULT 0, d2 VARCHAR(20) DEFAULT 'abcde',
@@ -1330,7 +1354,7 @@ @@ -1340,7 +1368,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -287,7 +305,7 @@ ...@@ -287,7 +305,7 @@
connection default; connection default;
ROLLBACK; ROLLBACK;
CHECKSUM TABLE big; CHECKSUM TABLE big;
@@ -1343,7 +1367,7 @@ @@ -1353,7 +1381,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/big'; WHERE name = 'test/big';
clust_index_size clust_index_size
...@@ -296,10 +314,10 @@ ...@@ -296,10 +314,10 @@
connection default; connection default;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged
DROP TABLE t1,t2,t3,t4,big; DROP TABLE t1,t2,t3,t4,big;
@@ -1431,5 +1455,5 @@ @@ -1446,5 +1474,5 @@
FROM information_schema.global_status FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column'; WHERE variable_name = 'innodb_instant_alter_column';
instants instants
-54 -57
+55 +58
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
...@@ -512,6 +512,13 @@ CHECK TABLE t1; ...@@ -512,6 +512,13 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
SET innodb_strict_mode = ON;
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 ADD d TEXT;
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
SET innodb_strict_mode = OFF;
CREATE TABLE t1 CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE, (id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
...@@ -969,6 +976,13 @@ CHECK TABLE t1; ...@@ -969,6 +976,13 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
SET innodb_strict_mode = ON;
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 ADD d TEXT;
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
SET innodb_strict_mode = OFF;
CREATE TABLE t1 CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE, (id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
...@@ -1426,10 +1440,17 @@ CHECK TABLE t1; ...@@ -1426,10 +1440,17 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
SET innodb_strict_mode = ON;
CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 ADD d TEXT;
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
SET innodb_strict_mode = OFF;
disconnect analyze; disconnect analyze;
SELECT variable_value-@old_instant instants SELECT variable_value-@old_instant instants
FROM information_schema.global_status FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column'; WHERE variable_name = 'innodb_instant_alter_column';
instants instants
54 57
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
...@@ -169,3 +169,4 @@ DROP FOREIGN KEY fk1, ...@@ -169,3 +169,4 @@ DROP FOREIGN KEY fk1,
CHANGE b d INT UNSIGNED, CHANGE b d INT UNSIGNED,
ADD c INT; ADD c INT;
DROP TABLE t2, t1; DROP TABLE t2, t1;
# End of 10.3 tests
...@@ -396,6 +396,18 @@ DELETE FROM t1; ...@@ -396,6 +396,18 @@ DELETE FROM t1;
CHECK TABLE t1; CHECK TABLE t1;
DROP TABLE t1; DROP TABLE t1;
# MDEV-21172 Memory leak during ADD PRIMARY KEY
SET innodb_strict_mode = ON;
eval CREATE TABLE t1 (a INT, b VARCHAR(500), c TEXT, UNIQUE(a,b)) $engine;
ALTER TABLE t1 ADD d TEXT;
--error 0,ER_TOO_BIG_ROWSIZE
ALTER TABLE t1 ADD PRIMARY KEY (b,a);
# Exploit MDEV-17468 to force the table definition to be reloaded
ALTER TABLE t1 ADD va INT AS (a) VIRTUAL;
DROP TABLE t1;
SET innodb_strict_mode = OFF;
dec $format; dec $format;
let $redundant_4k= 0; let $redundant_4k= 0;
} }
......
...@@ -169,3 +169,5 @@ ALTER TABLE t2 ...@@ -169,3 +169,5 @@ ALTER TABLE t2
CHANGE b d INT UNSIGNED, CHANGE b d INT UNSIGNED,
ADD c INT; ADD c INT;
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo # End of 10.3 tests
...@@ -5541,6 +5541,7 @@ prepare_inplace_alter_table_dict( ...@@ -5541,6 +5541,7 @@ prepare_inplace_alter_table_dict(
if (index) { if (index) {
dict_mem_index_free(index); dict_mem_index_free(index);
} }
error_handling_drop_uncached_1:
while (++a < ctx->num_to_add_index) { while (++a < ctx->num_to_add_index) {
dict_mem_index_free(ctx->add_index[a]); dict_mem_index_free(ctx->add_index[a]);
} }
...@@ -5552,7 +5553,7 @@ prepare_inplace_alter_table_dict( ...@@ -5552,7 +5553,7 @@ prepare_inplace_alter_table_dict(
ctx->add_index[a] = index; ctx->add_index[a] = index;
if (!info.row_size_is_acceptable(*index)) { if (!info.row_size_is_acceptable(*index)) {
error = DB_TOO_BIG_RECORD; error = DB_TOO_BIG_RECORD;
goto error_handling; goto error_handling_drop_uncached_1;
} }
index->parser = index_defs[a].parser; index->parser = index_defs[a].parser;
index->has_new_v_col = has_new_v_col; index->has_new_v_col = has_new_v_col;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment