From c76873f23ddf4ba36bb14dd3415c3073c51875bf Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 27 Sep 2019 17:46:10 +0530 Subject: [PATCH] MDEV-20688 Recovery crashes after unnecessarily reading a corrupted page The test encryption.innodb-redo-badkey was accidentally disabled until commit 23657a21018d0b3d0464bbd55236113ebcd3d4b7 enabled it recently. Once it was enabled, it started failing randomly. recv_recover_corrupt_page(): Do not assume that any redo log exists for the page. A page may be unnecessarily read by read-ahead. When noting the corruption, reset recv_addr->state to RECV_PROCESSED, so that even if the same page is re-read again, we will only decrement recv_sys->n_addrs once. --- .../encryption/r/innodb-redo-badkey.result | 7 ++--- .../encryption/t/innodb-redo-badkey.test | 7 ++--- storage/innobase/log/log0recv.cc | 26 ++++++++++--------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result index 101edbf5fdc..e551282667a 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result +++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result @@ -1,9 +1,10 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file .*test/t[1-4]\\.ibd cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); -call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t1\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); # Restart mysqld --file-key-management-filename=keys2.txt diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test index 70040f7b2de..502a3828835 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test @@ -5,10 +5,11 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file .*test/t[1-4]\\.ibd cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); -call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t1\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 2df1a8950d8..3068a510b4e 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2221,18 +2221,20 @@ void recv_recover_corrupt_page(page_id_t page_id) mutex_enter(&recv_sys->mutex); if (!recv_sys->apply_log_recs) { - mutex_exit(&recv_sys->mutex); - return; - } - - recv_addr_t* recv_addr = recv_get_fil_addr_struct( - page_id.space(), page_id.page_no()); - - ut_ad(recv_addr->state != RECV_WILL_NOT_READ); - - if (recv_addr->state != RECV_BEING_PROCESSED - && recv_addr->state != RECV_PROCESSED) { - recv_sys->n_addrs--; + } else if (recv_addr_t* recv_addr = recv_get_fil_addr_struct( + page_id.space(), page_id.page_no())) { + switch (recv_addr->state) { + case RECV_WILL_NOT_READ: + ut_ad(!"wrong state"); + break; + case RECV_BEING_PROCESSED: + case RECV_PROCESSED: + break; + default: + recv_addr->state = RECV_PROCESSED; + ut_ad(recv_sys->n_addrs); + recv_sys->n_addrs--; + } } mutex_exit(&recv_sys->mutex);