summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-11-01 13:35:47 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-11-01 13:35:47 +0200
commit993b8edf3fafc3c66aa265e445aac1c6421a29fd (patch)
treec65e30ac6b7f9d36dfbdf9eaa84fdb2aa35350e3
parentfdc4c3a29868e58656d659286ecdda189b034f8e (diff)
downloadmariadb-git-bb-10.6-MDEV-26933.tar.gz
MDEV-26933 InnoDB fails to detect page number mismatchbb-10.6-MDEV-26933
mtr_t::page_lock(): Validate the page number. ibuf_tree_root_get(): Remove assertions that became redundant. The assertions in btr_validate_level() are kind of redundant as well, but because they are ut_a(), they are also present in release builds, while the ones in mtr_t::page_lock() are only present in debug builds. btr_cur_position(): Do not duplicate an assertion that is part of page_cur_position(). dict_load_tablespace(): Introduce a new option DICT_ERR_IGNORE_TABLESPACE that will suppress loading a tablespace when a table is going to be dropped.
-rw-r--r--mysql-test/suite/innodb/r/alter_kill.result2
-rw-r--r--mysql-test/suite/innodb/t/alter_kill.test8
-rw-r--r--mysql-test/suite/innodb/t/log_corruption.test9
-rw-r--r--mysql-test/suite/innodb/t/page_id_innochecksum.test4
-rw-r--r--storage/innobase/dict/dict0crea.cc2
-rw-r--r--storage/innobase/dict/dict0load.cc7
-rw-r--r--storage/innobase/fts/fts0fts.cc4
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc2
-rw-r--r--storage/innobase/include/btr0cur.ic5
-rw-r--r--storage/innobase/include/dict0types.h8
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc2
11 files changed, 35 insertions, 18 deletions
diff --git a/mysql-test/suite/innodb/r/alter_kill.result b/mysql-test/suite/innodb/r/alter_kill.result
index 8195d8e8ed1..36b582c6d76 100644
--- a/mysql-test/suite/innodb/r/alter_kill.result
+++ b/mysql-test/suite/innodb/r/alter_kill.result
@@ -11,7 +11,7 @@ InnoDB 0 transactions not purged
connection default;
# Cleanly shutdown mysqld
disconnect con1;
-# Corrupt FIL_PAGE_OFFSET in bug16720368.ibd,
+# Corrupt FIL_PAGE_TYPE in bug16720368.ibd,
# and recompute innodb_checksum_algorithm=crc32
# restart
SELECT COUNT(*) FROM bug16720368;
diff --git a/mysql-test/suite/innodb/t/alter_kill.test b/mysql-test/suite/innodb/t/alter_kill.test
index 2313d63db69..a371a77971d 100644
--- a/mysql-test/suite/innodb/t/alter_kill.test
+++ b/mysql-test/suite/innodb/t/alter_kill.test
@@ -43,7 +43,7 @@ connection default;
disconnect con1;
--- echo # Corrupt FIL_PAGE_OFFSET in bug16720368.ibd,
+-- echo # Corrupt FIL_PAGE_TYPE in bug16720368.ibd,
-- echo # and recompute innodb_checksum_algorithm=crc32
perl;
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
@@ -56,7 +56,7 @@ die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
-substr($page,4,4)=pack("N",0xc001cafe);
+substr($page,24,2)='42';
my $polynomial = 0x82f63b78; # CRC-32C
if ($full_crc32)
{
@@ -86,7 +86,7 @@ INSERT INTO bug16720368_1 VALUES(1);
-- echo # Shut down the server to uncorrupt the data.
-- source include/shutdown_mysqld.inc
-# Uncorrupt the FIL_PAGE_OFFSET.
+# Uncorrupt the FIL_PAGE_TYPE.
perl;
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
my $file = "$ENV{MYSQLD_DATADIR}/test/bug16720368.ibd";
@@ -98,7 +98,7 @@ die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
-substr($page,4,4)=pack("N",3);
+substr($page,24,2)=pack("H*","45BF");
my $polynomial = 0x82f63b78; # CRC-32C
if ($full_crc32)
{
diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test
index 01b3da3f7ac..b9162be99db 100644
--- a/mysql-test/suite/innodb/t/log_corruption.test
+++ b/mysql-test/suite/innodb/t/log_corruption.test
@@ -57,7 +57,14 @@ my $body = pack("x[8]Nx[10]Nx[16312]", 768, 97937874);
my $ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial);
print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck);
# Dummy pages 1..6.
-print OUT chr(0) x (6 * 16384);
+$body = pack("x[16338]");
+for (my($page) = 1; $page < 7; $page++)
+{
+ ## FIL_PAGE_OFFSET
+ $head = pack("Nx[18]", $page);
+ $ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial);
+ print OUT pack("N",$ck).$head.pack("x[16350]Nx[4]",$ck);
+}
# Dictionary header page (page 7).
## FIL_PAGE_OFFSET
$head = pack("Nx[18]", 7);
diff --git a/mysql-test/suite/innodb/t/page_id_innochecksum.test b/mysql-test/suite/innodb/t/page_id_innochecksum.test
index 2726b3254da..f5166018dd1 100644
--- a/mysql-test/suite/innodb/t/page_id_innochecksum.test
+++ b/mysql-test/suite/innodb/t/page_id_innochecksum.test
@@ -61,5 +61,9 @@ let SEARCH_PATTERN=page id mismatch;
--source include/search_pattern_in_file.inc
--remove_file $resultlog
+# prevent purge from crashing on page ID mismatch
+let $restart_parameters=--innodb-force-recovery=2;
--source include/start_mysqld.inc
drop table t1;
+let $restart_parameters=;
+--source include/restart_mysqld.inc
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index c88227dbade..0f5e1761940 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -654,7 +654,7 @@ dict_build_index_def_step(
index = node->index;
table = dict_table_open_on_name(
- node->table_name, true, DICT_ERR_IGNORE_DROP);
+ node->table_name, true, DICT_ERR_IGNORE_TABLESPACE);
if (!table) {
return DB_TABLE_NOT_FOUND;
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 75cbfaa3587..e25a51f6fbc 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -2225,7 +2225,7 @@ dict_load_tablespace(
return;
}
- if (ignore_err == DICT_ERR_IGNORE_DROP) {
+ if (ignore_err >= DICT_ERR_IGNORE_TABLESPACE) {
table->file_unreadable = true;
return;
}
@@ -2412,6 +2412,11 @@ corrupted:
table->corrupted = true;
table->file_unreadable = true;
err = DB_CORRUPTION;
+ } else if (table->space->id
+ && ignore_err == DICT_ERR_IGNORE_DROP) {
+ /* Do not bother to load data from .ibd files
+ only to delete the .ibd files. */
+ goto corrupted;
} else {
const page_id_t page_id(table->space->id, root);
mtr.start();
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 4949005e0d7..2a3a780228d 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -1373,7 +1373,7 @@ fts_cache_add_doc(
static dberr_t fts_drop_table(trx_t *trx, const char *table_name, bool rename)
{
if (dict_table_t *table= dict_table_open_on_name(table_name, true,
- DICT_ERR_IGNORE_DROP))
+ DICT_ERR_IGNORE_TABLESPACE))
{
table->release();
if (rename)
@@ -1505,7 +1505,7 @@ static dberr_t fts_lock_table(trx_t *trx, const char *table_name)
ut_ad(purge_sys.must_wait_FTS());
if (dict_table_t *table= dict_table_open_on_name(table_name, false,
- DICT_ERR_IGNORE_DROP))
+ DICT_ERR_IGNORE_TABLESPACE))
{
dberr_t err= lock_table_for_trx(table, trx, LOCK_X);
/* Wait for purge threads to stop using the table. */
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index fbec3bee38c..8db0fc7d8ff 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -341,8 +341,6 @@ static buf_block_t *ibuf_tree_root_get(mtr_t *mtr)
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
0, RW_SX_LATCH, mtr);
- ut_ad(page_get_space_id(block->frame) == IBUF_SPACE_ID);
- ut_ad(page_get_page_no(block->frame) == FSP_IBUF_TREE_ROOT_PAGE_NO);
ut_ad(ibuf.empty == page_is_empty(block->frame));
return block;
diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic
index 8a45b714936..905dc28bd62 100644
--- a/storage/innobase/include/btr0cur.ic
+++ b/storage/innobase/include/btr0cur.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -109,10 +109,7 @@ btr_cur_position(
buf_block_t* block, /*!< in: buffer block of rec */
btr_cur_t* cursor) /*!< out: cursor */
{
- ut_ad(page_align(rec) == block->frame);
-
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
-
cursor->index = index;
}
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index 9a53ecdab8f..4f8b36bba74 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -82,8 +82,12 @@ enum dict_err_ignore_t {
incomplete index definitions. */
/** ignore all errors above */
DICT_ERR_IGNORE_ALL = 15,
- /** prepare to drop the table; do not attempt to load tablespace */
- DICT_ERR_IGNORE_DROP = 31
+ /** prepare some DDL operation;
+ do not attempt to load tablespace */
+ DICT_ERR_IGNORE_TABLESPACE = 31,
+ /** prepare to drop the table; do not attempt to load tablespace
+ or the metadata */
+ DICT_ERR_IGNORE_DROP = 63
};
/** Quiescing states for flushing tables to disk. */
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index ae3183703c2..a28edb9d1c5 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -1196,6 +1196,8 @@ void mtr_t::page_lock(buf_block_t *block, ulint rw_latch)
#endif /* BTR_CUR_HASH_ADAPT */
done:
+ ut_ad(page_id_t(page_get_space_id(block->frame),
+ page_get_page_no(block->frame)) == block->page.id());
memo_push(block, fix_type);
}