diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-11-01 13:35:47 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-11-01 13:35:47 +0200 |
commit | 993b8edf3fafc3c66aa265e445aac1c6421a29fd (patch) | |
tree | c65e30ac6b7f9d36dfbdf9eaa84fdb2aa35350e3 | |
parent | fdc4c3a29868e58656d659286ecdda189b034f8e (diff) | |
download | mariadb-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.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/alter_kill.test | 8 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/log_corruption.test | 9 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/page_id_innochecksum.test | 4 | ||||
-rw-r--r-- | storage/innobase/dict/dict0crea.cc | 2 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.cc | 7 | ||||
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 4 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.cc | 2 | ||||
-rw-r--r-- | storage/innobase/include/btr0cur.ic | 5 | ||||
-rw-r--r-- | storage/innobase/include/dict0types.h | 8 | ||||
-rw-r--r-- | storage/innobase/mtr/mtr0mtr.cc | 2 |
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); } |