From 0e1ba364a12b6569c75a7dadc38b7ef2b4910d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Jul 2019 18:24:54 +0300 Subject: [PATCH] MDEV-19916 Corruption after instant ADD/DROP and shrinking the tree btr_lift_page_up(): Correct the incorrect condition. page_validate(): Validate the page type. --- .../suite/innodb/r/instant_alter_debug.result | 27 +++++++++++++++++++ .../suite/innodb/t/instant_alter_debug.test | 25 +++++++++++++++++ storage/innobase/btr/btr0btr.cc | 3 ++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index ebb24d2a5e9..62df17e066f 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -236,4 +236,31 @@ a b c d 1 2 NULL 1 2 3 4 1 DROP TABLE t1; +# +# MDEV-19916 Corruption after instant ADD/DROP and shrinking the tree +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @old_limit = @@innodb_limit_optimistic_insert_debug; +SET GLOBAL innodb_limit_optimistic_insert_debug = 2; +INSERT INTO t1 VALUES (1),(5),(4),(3),(2); +SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit; +ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT; +SET @old_defragment = @@innodb_defragment; +SET GLOBAL innodb_defragment = 1; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SET GLOBAL innodb_defragment = @old_defragment; +ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SELECT * FROM t1; +a b vb +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +DROP TABLE t1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index e54623b9cbd..5b8624a3186 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -267,4 +267,29 @@ SET DEBUG_SYNC = RESET; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-19916 Corruption after instant ADD/DROP and shrinking the tree +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; + +# Create an index tree with 2 levels of node pointer pages. + +SET @old_limit = @@innodb_limit_optimistic_insert_debug; +SET GLOBAL innodb_limit_optimistic_insert_debug = 2; +INSERT INTO t1 VALUES (1),(5),(4),(3),(2); +SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit; + +ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT; + +SET @old_defragment = @@innodb_defragment; +SET GLOBAL innodb_defragment = 1; +OPTIMIZE TABLE t1; +SET GLOBAL innodb_defragment = @old_defragment; + +# Exploit MDEV-17468 to force the table definition to be reloaded +ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; +CHECK TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index abbf29af7bb..e0fce3fc132 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -3453,7 +3453,8 @@ btr_lift_page_up( /* btr_page_empty() is supposed to zero-initialize the field. */ ut_ad(!page_get_instant(father_block->frame)); - if (page_level == 0 && index->is_instant()) { + if (index->is_instant() + && father_block->page.id.page_no() == root_page_no) { ut_ad(!father_page_zip); byte* page_type = father_block->frame + FIL_PAGE_TYPE; ut_ad(mach_read_from_2(page_type) == FIL_PAGE_INDEX);