From 5f22e83a295c0439f1c73a6f666a3b58f2397632 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 19 Nov 2021 12:17:14 +0300 Subject: [PATCH 1/3] Make the Optimizer Trace of reqular query and PS EXECUTE be identical Print this piece when we've just made the choice to convert to semi-join. Also, print it when we've already made that choice before: transformation": { "select_id": 2, "from": "IN (SELECT)", "to": "semijoin", "chosen": true } --- mysql-test/main/opt_trace,ps.rdiff | 92 ------------------------------ mysql-test/main/opt_trace.test | 1 - sql/opt_subselect.cc | 9 +++ 3 files changed, 9 insertions(+), 93 deletions(-) delete mode 100644 mysql-test/main/opt_trace,ps.rdiff diff --git a/mysql-test/main/opt_trace,ps.rdiff b/mysql-test/main/opt_trace,ps.rdiff deleted file mode 100644 index 3e2218de673..00000000000 --- a/mysql-test/main/opt_trace,ps.rdiff +++ /dev/null @@ -1,92 +0,0 @@ ---- /Users/shulga/projects/mariadb/server-10.6/mysql-test/main/opt_trace.result 2021-07-21 19:17:11.000000000 +0700 -+++ /Users/shulga/projects/mariadb/server-10.6/mysql-test/main/opt_trace.reject 2021-07-21 19:17:48.000000000 +0700 -@@ -2829,14 +2829,6 @@ - } - }, - { -- "transformation": { -- "select_id": 2, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#2 */ select t10.pk from t10" - } - ] -@@ -4402,14 +4394,6 @@ - } - }, - { -- "transformation": { -- "select_id": 2, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#2 */ select t_inner_1.a from t1 t_inner_1 join t1 t_inner_2" - } - ] -@@ -4852,14 +4836,6 @@ - } - }, - { -- "transformation": { -- "select_id": 2, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1" - } - ] -@@ -4879,14 +4855,6 @@ - } - }, - { -- "transformation": { -- "select_id": 3, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4" - } - ] -@@ -6432,14 +6400,6 @@ - } - }, - { -- "transformation": { -- "select_id": 2, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1" - } - ] -@@ -6459,14 +6419,6 @@ - } - }, - { -- "transformation": { -- "select_id": 3, -- "from": "IN (SELECT)", -- "to": "semijoin", -- "chosen": true -- } -- }, -- { - "expanded_query": "/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4" - } - ] diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 70223560187..402caf2a165 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -1,6 +1,5 @@ --source include/not_embedded.inc --source include/have_sequence.inc ---source include/protocol.inc SELECT table_name, column_name FROM information_schema.columns where table_name="OPTIMIZER_TRACE"; set optimizer_trace="enabled=on"; show variables like 'optimizer_trace'; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index dc93535bd87..99f75d9ad2f 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -717,6 +717,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join) if (arena) thd->restore_active_arena(arena, &backup); in_subs->is_registered_semijoin= TRUE; + } + + /* + Print the transformation into trace. Do it when we've just set + is_registered_semijoin=TRUE above, and also do it when we've already + had it set. + */ + if (in_subs->is_registered_semijoin) + { OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform, select_lex->select_number, "IN (SELECT)", "semijoin"); From cab8f4b552d234c8642f87fae28ecb098392c381 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 15 Nov 2021 18:19:53 +0530 Subject: [PATCH 2/3] MDEV-27014 InnoDB fails to restore page 0 from the doublewrite buffer InnoDB fails to restore page0 from doublewrite buffer when the tablespace is being deferred. In that case, InnoDB doesn't find INIT_PAGE redo log record for page0 and it leads to failure. InnoDB should recovery page0 from doublewrite buffer. --- storage/innobase/fil/fil0fil.cc | 2 +- storage/innobase/fsp/fsp0file.cc | 32 +++++++++++++++++++++-------- storage/innobase/include/fsp0file.h | 3 ++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 681cee32fd5..00ee1c71981 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2576,7 +2576,7 @@ fil_ibd_load( /* Read and validate the first page of the tablespace. Assign a tablespace name based on the tablespace type. */ - switch (file.validate_for_recovery()) { + switch (file.validate_for_recovery(&space_id)) { os_offset_t minimum_size; case DB_SUCCESS: deferred_space = file.m_defer; diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 9a552e6dc5c..fbf87843550 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -387,10 +387,11 @@ exist and be successfully opened. We initially open it in read-only mode because we just want to read the SpaceID. However, if the first page is corrupt and needs to be restored from the doublewrite buffer, we will reopen it in write mode and ry to restore that page. +@param space_id space id to validate for recovery @retval DB_SUCCESS if tablespace is valid, DB_ERROR if not. m_is_valid is also set true on success, else false. */ dberr_t -Datafile::validate_for_recovery() +Datafile::validate_for_recovery(ulint *space_id) { dberr_t err; @@ -433,15 +434,25 @@ Datafile::validate_for_recovery() } } - if (m_space_id == ULINT_UNDEFINED) { - return DB_SUCCESS; /* empty file */ + bool empty_tablespace= (m_space_id == ULINT_UNDEFINED); + if (empty_tablespace && space_id) { + /* Set space id to find out whether + the page exist in double write buffer */ + m_space_id = *space_id; } if (restore_from_doublewrite()) { - if (m_defer) { + if (!m_defer) { + return DB_CORRUPTION; + } else if (!empty_tablespace) { return err; + } else { + /* Reset the space id. InnoDB + could rebuild the page0 + from redo log */ + m_space_id = ULINT_UNDEFINED; + return DB_SUCCESS; /* empty file */ } - return(DB_CORRUPTION); } /* Free the previously read first page and then re-validate. */ @@ -769,10 +780,13 @@ Datafile::restore_from_doublewrite() in the doublewrite buffer, then the recovery is going to fail now. Hence this is treated as an error. */ - ib::error() - << "Corrupted page " << page_id - << " of datafile '" << m_filepath - << "' could not be found in the doublewrite buffer."; + if (!m_defer) { + ib::error() + << "Corrupted page " << page_id + << " of datafile '" << m_filepath + << "' could not be found in the " + << "doublewrite buffer."; + } return(true); } diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 8c11d61c5aa..5978e2d0576 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -207,9 +207,10 @@ public: However, if the first page is corrupt and needs to be restored from the doublewrite buffer, we will reopen it in write mode and ry to restore that page. + @param space_id space id to validate for recovery @retval DB_SUCCESS if tablespace is valid, DB_ERROR if not. m_is_valid is also set true on success, else false. */ - dberr_t validate_for_recovery() + dberr_t validate_for_recovery(ulint *space_id=nullptr) MY_ATTRIBUTE((warn_unused_result)); /** Checks the consistency of the first page of a datafile when the From e0e24b180d090d7ee378c097ab02df891b61a965 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 1 Dec 2021 13:37:06 +0530 Subject: [PATCH 3/3] MDEV-27014 InnoDB fails to restore page 0 from the doublewrite buffer - Replaced the pointer parameter of validate_for_recovery() with uint32_t --- storage/innobase/fil/fil0fil.cc | 3 ++- storage/innobase/fsp/fsp0file.cc | 4 ++-- storage/innobase/include/fsp0file.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 00ee1c71981..1bedcb56077 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2576,7 +2576,8 @@ fil_ibd_load( /* Read and validate the first page of the tablespace. Assign a tablespace name based on the tablespace type. */ - switch (file.validate_for_recovery(&space_id)) { + switch (file.validate_for_recovery( + static_cast(space_id))) { os_offset_t minimum_size; case DB_SUCCESS: deferred_space = file.m_defer; diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index fbf87843550..2ea4a3a85ca 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -391,7 +391,7 @@ reopen it in write mode and ry to restore that page. @retval DB_SUCCESS if tablespace is valid, DB_ERROR if not. m_is_valid is also set true on success, else false. */ dberr_t -Datafile::validate_for_recovery(ulint *space_id) +Datafile::validate_for_recovery(uint32_t space_id) { dberr_t err; @@ -438,7 +438,7 @@ Datafile::validate_for_recovery(ulint *space_id) if (empty_tablespace && space_id) { /* Set space id to find out whether the page exist in double write buffer */ - m_space_id = *space_id; + m_space_id = space_id; } if (restore_from_doublewrite()) { diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 5978e2d0576..d87134d2913 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -210,7 +210,7 @@ public: @param space_id space id to validate for recovery @retval DB_SUCCESS if tablespace is valid, DB_ERROR if not. m_is_valid is also set true on success, else false. */ - dberr_t validate_for_recovery(ulint *space_id=nullptr) + dberr_t validate_for_recovery(uint32_t space_id=0) MY_ATTRIBUTE((warn_unused_result)); /** Checks the consistency of the first page of a datafile when the