summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-09-21 13:29:27 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-09-24 18:44:16 +0530
commit76972163711f965402d51055f081ab51ae4a3bb7 (patch)
treeb82ca24ec9ddd2a70b074012d6031902c723e1c8
parentd95361107c07b6e8257a7a82c41b18af64ab8d89 (diff)
downloadmariadb-git-bb-10.6-MDEV-26631.tar.gz
MDEV-26631 InnoDB fails to fetch page from doublewrite bufferbb-10.6-MDEV-26631
Problem: ======== InnoDB fails to fetch the page0 from dblwr if page0 is corrupted.In that case, InnoDB defers the tablespace and doesn't find the INIT_PAGE redo log record for page0 and it leads to failure. Solution: ========= InnoDB should recover page0 from dblwr if space_id can be found for deferred tablespace.
-rw-r--r--mysql-test/suite/innodb/r/doublewrite.result1
-rw-r--r--mysql-test/suite/innodb/t/doublewrite.test2
-rw-r--r--storage/innobase/fsp/fsp0file.cc32
3 files changed, 27 insertions, 8 deletions
diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result
index 234d58012d3..ba1965ed4cd 100644
--- a/mysql-test/suite/innodb/r/doublewrite.result
+++ b/mysql-test/suite/innodb/r/doublewrite.result
@@ -65,6 +65,7 @@ where name = 'test/t1';
# Ensure that dirty pages of table t1 is flushed.
flush tables t1 for export;
unlock tables;
+set global innodb_log_checkpoint_now=1;
begin;
insert into t1 values (6, repeat('%', 12));
# Make the first page dirty for table t1
diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test
index cedd2c9942b..d8dac955348 100644
--- a/mysql-test/suite/innodb/t/doublewrite.test
+++ b/mysql-test/suite/innodb/t/doublewrite.test
@@ -159,6 +159,8 @@ where name = 'test/t1';
flush tables t1 for export;
unlock tables;
+set global innodb_log_checkpoint_now=1;
+
begin;
insert into t1 values (6, repeat('%', 12));
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index aebe6c9ce23..9a552e6dc5c 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -400,10 +400,19 @@ Datafile::validate_for_recovery()
err = validate_first_page(0);
switch (err) {
- case DB_SUCCESS:
case DB_TABLESPACE_EXISTS:
break;
-
+ case DB_SUCCESS:
+ if (!m_defer || !m_space_id) {
+ break;
+ }
+ /* InnoDB should check whether the deferred
+ tablespace page0 can be recovered from
+ double write buffer. InnoDB should try
+ to recover only if m_space_id exists because
+ dblwr pages can be searched via {space_id, 0}.
+ m_space_id is set in read_first_page(). */
+ /* fall through */
default:
/* Re-open the file in read-write mode Attempt to restore
page 0 from doublewrite and read the space ID from a survey
@@ -414,23 +423,30 @@ Datafile::validate_for_recovery()
return(err);
}
- err = find_space_id();
- if (err != DB_SUCCESS || m_space_id == 0) {
- ib::error() << "Datafile '" << m_filepath << "' is"
- " corrupted. Cannot determine the space ID from"
- " the first 64 pages.";
- return(err);
+ if (!m_defer) {
+ err = find_space_id();
+ if (err != DB_SUCCESS || m_space_id == 0) {
+ ib::error() << "Datafile '" << m_filepath
+ << "' is corrupted. Cannot determine "
+ "the space ID from the first 64 pages.";
+ return(err);
+ }
}
+
if (m_space_id == ULINT_UNDEFINED) {
return DB_SUCCESS; /* empty file */
}
if (restore_from_doublewrite()) {
+ if (m_defer) {
+ return err;
+ }
return(DB_CORRUPTION);
}
/* Free the previously read first page and then re-validate. */
free_first_page();
+ m_defer = false;
err = validate_first_page(0);
}