From b47cec6c551ddc95205b366c5c464fcebd9f85a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Mar 2019 18:10:23 +0200 Subject: [PATCH] MDEV-18879/MDEV-18972 Corrupted record inserted by FOREIGN KEY operation row_ins_foreign_check_on_constraint(): When constructing cascade->historical_row for tables WITH SYSTEM VERSIONING, use the appropriate mode ROW_COPY_DATA, because the pointers will be stale after mtr_commit() is invoked. --- mysql-test/suite/versioning/r/foreign.result | 88 ++++++++++++++++++++ mysql-test/suite/versioning/t/foreign.test | 79 ++++++++++++++++++ storage/innobase/row/row0ins.cc | 4 +- 3 files changed, 169 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result index a7a84f539bf..e6e2d710fcf 100644 --- a/mysql-test/suite/versioning/r/foreign.result +++ b/mysql-test/suite/versioning/r/foreign.result @@ -299,3 +299,91 @@ UPDATE t2 SET f2= 2; ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)) DELETE FROM t2; DROP TABLE t2, t1; +# +# MDEV-18879 Corrupted record inserted by FOREIGN KEY operation +# +SET timestamp = 1; +SET time_zone='+02:00'; +SELECT now(); +now() +1970-01-01 02:00:01 +CREATE TABLE t1 ( +pk INT UNSIGNED PRIMARY KEY, +f1 varchar(255) CHARACTER SET ucs2, +f2 longtext CHARACTER SET ucs2, +f3 varchar(255), +f4 char(255), +f5 longtext CHARACTER SET ucs2, +f6 INT UNSIGNED, +f7 INT UNSIGNED, +f8 INT UNSIGNED, +f9 INT UNSIGNED, +f10 INT UNSIGNED, +f11 INT UNSIGNED, +f12 varchar(255) CHARACTER SET ucs2, +f13 char(255) CHARACTER SET ucs2, +f14 char(255) CHARACTER SET ucs2, +f15 varchar(255), +f16 longtext, +f17 char(255) +) ENGINE=InnoDB WITH SYSTEM VERSIONING; +INSERT INTO t1 VALUES +(1, 'a', 'e', 'f', 'a', 'generate', 1, 2, 3, 4, 5, 6, 'main', 'against', 'b', 'u', 'explode', 'tomorrow'), +(2, REPEAT('a',127), 'f', 'k', 'game', 'g', 2, 3, 4, 5, 6, 7, REPEAT('o',222), 'oven', 'flower', REPEAT('r',120), 'l', 'g'), +(3, 'weekly', 'x', 'v', 'r', 'c', 3, 4, 5, 6, 7, 8, 'validity', 'y', 'h', 'oxygen', 'venture', 'uncertainty'), +(4, 'r', 't', REPEAT('b',153), 'modern', 'h', 4, 5, 6, 7, 8, 9, REPEAT('g',128), 'a', 'w', 'f', 'b', 'b'), +(5, 'h', 'y', REPEAT('v',107), 'knife', 'profession', 5, 6, 7, 8, 9, 0, 'infection', 'u', 'likelihood', REPEAT('n',149), 'folk', 'd'), +(6, 'g', 'violent', REPEAT('o',28), 'capital', 'p', 6, 7, 8, 9, 0, 1, 'w', 'patron', 'd', 'y', 'originally', 'k'), +(7, 'k', 'uncomfortable', REPEAT('v',248), 'y', 'link', 7, 8, 9, 0, 1, 2, REPEAT('j',204), 'j', 'statute', 'emphasis', 'u', 'water'), +(8, 'preparation', 'water', 'suck', 'silver', 'a', 8, 9, 0, 1, 2, 3, 'h', 'q', 'o', 't', 'k', 'y'), +(9, 'y', 'f', 'e', 'a', 'dawn', 9, 0, 1, 2, 3, 4, 'peak', 'parking', 'b', 't', 'timber', 'c'), +(10, REPEAT('h',78), 'apologize', 'direct', 'u', 'frankly', 0, 1, 2, 3, 4, 5, 'h', 'exhibit', 'f', 'd', 'effective', 'c'), +(11, 'i', 'h', 'a', 'y', 'u', 1, 2, 3, 4, 5, 6, 'l', 'b', 'm', 'respond', 'ideological', 'credibility'); +CREATE TABLE t2 ( +pk int primary key, +f char(255) CHARACTER SET ucs2, +key(f) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,'against'),(2,'q'); +SET SQL_MODE= ''; +SET timestamp = 2; +SELECT * FROM t1 INTO OUTFILE 't1.data'; +SET timestamp = 3; +UPDATE t1 SET f13 = 'q'; +SET timestamp = 4; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +Warnings: +Warning 1265 Data truncated for column 'f12' at row 2 +Warning 1265 Data truncated for column 'f12' at row 4 +Warning 1265 Data truncated for column 'f12' at row 7 +SELECT * FROM t1 INTO OUTFILE 't1.data.2' ; +SET timestamp = 5; +LOAD DATA INFILE 't1.data.2' REPLACE INTO TABLE t1; +Warnings: +Warning 1265 Data truncated for column 'f1' at row 2 +Warning 1265 Data truncated for column 'f12' at row 2 +Warning 1265 Data truncated for column 'f12' at row 4 +Warning 1265 Data truncated for column 'f12' at row 7 +Warning 1265 Data truncated for column 'f1' at row 10 +SELECT * FROM t2 INTO OUTFILE 't2.data'; +SET timestamp = 6; +LOAD DATA INFILE 't2.data' REPLACE INTO TABLE t2; +SET FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 ADD FOREIGN KEY (f13) REFERENCES t2 (f) ON DELETE SET NULL; +SET timestamp = 7; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +Warnings: +Warning 1265 Data truncated for column 'f12' at row 2 +Warning 1265 Data truncated for column 'f12' at row 4 +Warning 1265 Data truncated for column 'f12' at row 7 +SET FOREIGN_KEY_CHECKS = ON; +SET SESSION SQL_MODE= 'NO_BACKSLASH_ESCAPES'; +SET timestamp = 8; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +Warnings: +Warning 1265 Data truncated for column 'f12' at row 2 +Warning 1265 Data truncated for column 'f12' at row 4 +Warning 1265 Data truncated for column 'f12' at row 7 +SET timestamp = 9; +REPLACE INTO t2 SELECT * FROM t2; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test index 075f15a216c..1f899773128 100644 --- a/mysql-test/suite/versioning/t/foreign.test +++ b/mysql-test/suite/versioning/t/foreign.test @@ -330,5 +330,84 @@ DELETE FROM t2; DROP TABLE t2, t1; +--echo # +--echo # MDEV-18879 Corrupted record inserted by FOREIGN KEY operation +--echo # +SET timestamp = 1; +SET time_zone='+02:00'; +SELECT now(); +CREATE TABLE t1 ( + pk INT UNSIGNED PRIMARY KEY, + f1 varchar(255) CHARACTER SET ucs2, + f2 longtext CHARACTER SET ucs2, + f3 varchar(255), + f4 char(255), + f5 longtext CHARACTER SET ucs2, + f6 INT UNSIGNED, + f7 INT UNSIGNED, + f8 INT UNSIGNED, + f9 INT UNSIGNED, + f10 INT UNSIGNED, + f11 INT UNSIGNED, + f12 varchar(255) CHARACTER SET ucs2, + f13 char(255) CHARACTER SET ucs2, + f14 char(255) CHARACTER SET ucs2, + f15 varchar(255), + f16 longtext, + f17 char(255) +) ENGINE=InnoDB WITH SYSTEM VERSIONING; + +INSERT INTO t1 VALUES +(1, 'a', 'e', 'f', 'a', 'generate', 1, 2, 3, 4, 5, 6, 'main', 'against', 'b', 'u', 'explode', 'tomorrow'), +(2, REPEAT('a',127), 'f', 'k', 'game', 'g', 2, 3, 4, 5, 6, 7, REPEAT('o',222), 'oven', 'flower', REPEAT('r',120), 'l', 'g'), +(3, 'weekly', 'x', 'v', 'r', 'c', 3, 4, 5, 6, 7, 8, 'validity', 'y', 'h', 'oxygen', 'venture', 'uncertainty'), +(4, 'r', 't', REPEAT('b',153), 'modern', 'h', 4, 5, 6, 7, 8, 9, REPEAT('g',128), 'a', 'w', 'f', 'b', 'b'), +(5, 'h', 'y', REPEAT('v',107), 'knife', 'profession', 5, 6, 7, 8, 9, 0, 'infection', 'u', 'likelihood', REPEAT('n',149), 'folk', 'd'), +(6, 'g', 'violent', REPEAT('o',28), 'capital', 'p', 6, 7, 8, 9, 0, 1, 'w', 'patron', 'd', 'y', 'originally', 'k'), +(7, 'k', 'uncomfortable', REPEAT('v',248), 'y', 'link', 7, 8, 9, 0, 1, 2, REPEAT('j',204), 'j', 'statute', 'emphasis', 'u', 'water'), +(8, 'preparation', 'water', 'suck', 'silver', 'a', 8, 9, 0, 1, 2, 3, 'h', 'q', 'o', 't', 'k', 'y'), +(9, 'y', 'f', 'e', 'a', 'dawn', 9, 0, 1, 2, 3, 4, 'peak', 'parking', 'b', 't', 'timber', 'c'), +(10, REPEAT('h',78), 'apologize', 'direct', 'u', 'frankly', 0, 1, 2, 3, 4, 5, 'h', 'exhibit', 'f', 'd', 'effective', 'c'), +(11, 'i', 'h', 'a', 'y', 'u', 1, 2, 3, 4, 5, 6, 'l', 'b', 'm', 'respond', 'ideological', 'credibility'); + +CREATE TABLE t2 ( + pk int primary key, + f char(255) CHARACTER SET ucs2, + key(f) +) ENGINE=InnoDB; + +INSERT INTO t2 VALUES (1,'against'),(2,'q'); + +SET SQL_MODE= ''; +SET timestamp = 2; +SELECT * FROM t1 INTO OUTFILE 't1.data'; +SET timestamp = 3; +UPDATE t1 SET f13 = 'q'; +SET timestamp = 4; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +SELECT * FROM t1 INTO OUTFILE 't1.data.2' ; +SET timestamp = 5; +LOAD DATA INFILE 't1.data.2' REPLACE INTO TABLE t1; +SELECT * FROM t2 INTO OUTFILE 't2.data'; +SET timestamp = 6; +LOAD DATA INFILE 't2.data' REPLACE INTO TABLE t2; +SET FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 ADD FOREIGN KEY (f13) REFERENCES t2 (f) ON DELETE SET NULL; +SET timestamp = 7; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +SET FOREIGN_KEY_CHECKS = ON; + +SET SESSION SQL_MODE= 'NO_BACKSLASH_ESCAPES'; +SET timestamp = 8; +LOAD DATA INFILE 't1.data' REPLACE INTO TABLE t1; +SET timestamp = 9; +REPLACE INTO t2 SELECT * FROM t2; + +# Cleanup +DROP TABLE t1, t2; +--let $datadir= `select @@datadir` +--remove_file $datadir/test/t1.data +--remove_file $datadir/test/t1.data.2 +--remove_file $datadir/test/t2.data --source suite/versioning/common_finish.inc diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 94a4ad3d122..d596900a3c3 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1413,9 +1413,9 @@ row_ins_foreign_check_on_constraint( if (table->versioned() && cascade->is_delete != PLAIN_DELETE && cascade->update->affects_versioned()) { ut_ad(!cascade->historical_heap); - cascade->historical_heap = mem_heap_create(128); + cascade->historical_heap = mem_heap_create(srv_page_size); cascade->historical_row = row_build( - ROW_COPY_POINTERS, clust_index, clust_rec, NULL, table, + ROW_COPY_DATA, clust_index, clust_rec, NULL, table, NULL, NULL, NULL, cascade->historical_heap); }