From fed0d85de753172e48623b87652af03935d38862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 19 Sep 2022 11:46:25 +0300 Subject: [PATCH] MDEV-29559 Recovery of INSERT_HEAP_DYNAMIC into secondary index fails log_phys_t::apply(): When parsing an INSERT_HEAP_DYNAMIC record, allow ll==rlen to hold for the last part. A secondary index record may inherit all preceding bytes from the infimum pseudo-record. For INSERT_HEAP_REDUNDANT, some header bytes will always be present because the header will never be copied from the page infimum. We will tolerate ll==rlen also in that case to be consistent with the parsing of INSERT_HEAP_DYNAMIC. --- .../suite/innodb/r/recovery_shutdown.result | 31 +++++++------------ .../suite/innodb/t/recovery_shutdown.test | 30 +++++------------- storage/innobase/log/log0recv.cc | 4 +-- 3 files changed, 21 insertions(+), 44 deletions(-) diff --git a/mysql-test/suite/innodb/r/recovery_shutdown.result b/mysql-test/suite/innodb/r/recovery_shutdown.result index dc785d580fe..6f7ca6e0d1d 100644 --- a/mysql-test/suite/innodb/r/recovery_shutdown.result +++ b/mysql-test/suite/innodb/r/recovery_shutdown.result @@ -4,13 +4,10 @@ call mtr.add_suppression("Found 1 prepared XA transactions"); # MDEV-13797 InnoDB may hang if shutdown is initiated soon after startup # while rolling back recovered incomplete transactions # -CREATE TABLE t (a INT) ENGINE=InnoDB; -BEGIN; -COMMIT; connect con$c,localhost,root,,; CREATE TABLE t8 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; XA START 'x'; -INSERT INTO t8 (a) SELECT NULL FROM t; +INSERT INTO t8 (a) SELECT NULL FROM seq_1_to_100; UPDATE t8 SET a=a+100, b=a; DELETE FROM t8; XA END 'x'; @@ -18,58 +15,54 @@ XA PREPARE 'x'; connect con$c,localhost,root,,; CREATE TABLE t7 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t7 (a) SELECT NULL FROM t; +INSERT INTO t7 (a) SELECT NULL FROM seq_1_to_100; UPDATE t7 SET a=a+100, b=a; DELETE FROM t7; connect con$c,localhost,root,,; CREATE TABLE t6 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t6 (a) SELECT NULL FROM t; +INSERT INTO t6 (a) SELECT NULL FROM seq_1_to_100; UPDATE t6 SET a=a+100, b=a; DELETE FROM t6; connect con$c,localhost,root,,; CREATE TABLE t5 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t5 (a) SELECT NULL FROM t; +INSERT INTO t5 (a) SELECT NULL FROM seq_1_to_100; UPDATE t5 SET a=a+100, b=a; DELETE FROM t5; connect con$c,localhost,root,,; CREATE TABLE t4 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t4 (a) SELECT NULL FROM t; +INSERT INTO t4 (a) SELECT NULL FROM seq_1_to_100; UPDATE t4 SET a=a+100, b=a; DELETE FROM t4; connect con$c,localhost,root,,; CREATE TABLE t3 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t3 (a) SELECT NULL FROM t; +INSERT INTO t3 (a) SELECT NULL FROM seq_1_to_100; UPDATE t3 SET a=a+100, b=a; DELETE FROM t3; connect con$c,localhost,root,,; CREATE TABLE t2 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t2 (a) SELECT NULL FROM t; +INSERT INTO t2 (a) SELECT NULL FROM seq_1_to_100; UPDATE t2 SET a=a+100, b=a; DELETE FROM t2; connect con$c,localhost,root,,; CREATE TABLE t1 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -INSERT INTO t1 (a) SELECT NULL FROM t; +INSERT INTO t1 (a) SELECT NULL FROM seq_1_to_100; UPDATE t1 SET a=a+100, b=a; DELETE FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; +INSERT INTO t1(a) SELECT NULL FROM seq_1_to_1600; connection default; SET GLOBAL innodb_flush_log_at_trx_commit=1; -CREATE TABLE u(a SERIAL) ENGINE=INNODB; +CREATE TABLE MDEV_29559 (a TINYINT UNSIGNED PRIMARY KEY, KEY(a)) ENGINE=InnoDB; +INSERT INTO MDEV_29559 VALUES (0x69); FLUSH TABLES; # restart -# restart XA RECOVER; formatID gtrid_length bqual_length data 1 1 0 x # restart -DROP TABLE t,u; +DROP TABLE MDEV_29559; diff --git a/mysql-test/suite/innodb/t/recovery_shutdown.test b/mysql-test/suite/innodb/t/recovery_shutdown.test index d9079f2e42c..85e49b255d3 100644 --- a/mysql-test/suite/innodb/t/recovery_shutdown.test +++ b/mysql-test/suite/innodb/t/recovery_shutdown.test @@ -1,8 +1,6 @@ --source include/have_innodb.inc --source include/not_embedded.inc -# Valgrind has to be disabled as killing the server hard gives a lot of -# leak warnings ---source include/not_valgrind.inc +--source include/have_sequence.inc # Flush any open myisam tables from previous tests FLUSH TABLES; @@ -13,24 +11,14 @@ call mtr.add_suppression("Found 1 prepared XA transactions"); --echo # while rolling back recovered incomplete transactions --echo # -CREATE TABLE t (a INT) ENGINE=InnoDB; let $size = 100; let $trx = 8; -let $c = $size; -BEGIN; ---disable_query_log -while ($c) { -INSERT INTO t VALUES(); -dec $c; -} ---enable_query_log -COMMIT; let $c = $trx; connect (con$c,localhost,root,,); eval CREATE TABLE t$c (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; XA START 'x'; -eval INSERT INTO t$c (a) SELECT NULL FROM t; +eval INSERT INTO t$c (a) SELECT NULL FROM seq_1_to_$size; eval UPDATE t$c SET a=a+$size, b=a; eval DELETE FROM t$c; XA END 'x'; @@ -41,28 +29,24 @@ while ($c) connect (con$c,localhost,root,,); eval CREATE TABLE t$c (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB; BEGIN; -eval INSERT INTO t$c (a) SELECT NULL FROM t; +eval INSERT INTO t$c (a) SELECT NULL FROM seq_1_to_$size; eval UPDATE t$c SET a=a+$size, b=a; eval DELETE FROM t$c; dec $c; } -INSERT INTO t1(a) SELECT NULL FROM t; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; -INSERT INTO t1(a) SELECT NULL FROM t1; +INSERT INTO t1(a) SELECT NULL FROM seq_1_to_1600; --connection default SET GLOBAL innodb_flush_log_at_trx_commit=1; -CREATE TABLE u(a SERIAL) ENGINE=INNODB; +CREATE TABLE MDEV_29559 (a TINYINT UNSIGNED PRIMARY KEY, KEY(a)) ENGINE=InnoDB; +INSERT INTO MDEV_29559 VALUES (0x69); FLUSH TABLES; --let $shutdown_timeout=0 --source include/restart_mysqld.inc --let $shutdown_timeout=60 ---source include/restart_mysqld.inc # Perform a slow shutdown in order to roll back all recovered transactions # and to avoid locking conflicts with the DROP TABLE below. @@ -85,4 +69,4 @@ dec $c; } --enable_query_log -DROP TABLE t,u; +DROP TABLE MDEV_29559; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index f789e061d9b..44b77c03952 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -359,7 +359,7 @@ page_corrupted: rlen-= ll; l+= ll; ll= mlog_decode_varint_length(*l); - if (UNIV_UNLIKELY(ll > 3 || ll >= rlen)) + if (UNIV_UNLIKELY(ll > 3 || ll > rlen)) goto record_corrupted; size_t data_c= mlog_decode_varint(l); ut_ad(data_c != MLOG_DECODE_ERROR); @@ -386,7 +386,7 @@ page_corrupted: rlen-= ll; l+= ll; ll= mlog_decode_varint_length(*l); - if (UNIV_UNLIKELY(ll > 2 || ll >= rlen)) + if (UNIV_UNLIKELY(ll > 2 || ll > rlen)) goto record_corrupted; size_t data_c= mlog_decode_varint(l); rlen-= ll;