From 19c721631ef21bcf3ce3ea3a036da5e234b0f49c Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 6 Jun 2022 22:21:22 +0300 Subject: [PATCH 1/8] MDEV-28749: restore_prev_nj_state() doesn't update cur_sj_inner_tables correctly (Try 2) (Cherry-pick back into 10.3) The code that updates semi-join optimization state for a join order prefix had several bugs. The visible effect was bad optimization for FirstMatch or LooseScan strategies: they either weren't considered when they should have been, or considered when they shouldn't have been. In order to hit the bug, the optimizer needs to consider several different join prefixes in a certain order. Queries with "obvious" query plans which prune all join orders except one are not affected. Internally, the bugs in updates of semi-join state were: 1. restore_prev_sj_state() assumed that "we assume remaining_tables doesnt contain @tab" which wasn't true. 2. Another bug in this function: it did remove bits from join->cur_sj_inner_tables but never added them. 3. greedy_search() adds tables into the join prefix but neglects to update the semi-join optimization state. (It does update nested outer join state, see this call: check_interleaving_with_nj(best_table) but there's no matching call to update the semi-join state. (This wasn't visible because most of the state is in the POSITION structure which is updated. But there is also state in JOIN, too) The patch: - Fixes all of the above - Adds JOIN::dbug_verify_sj_inner_tables() which is used to verify the state is correct at every step. - Renames advance_sj_state() to optimize_semi_joins(). = Introduces update_sj_state() which ideally should have been called "advance_sj_state" but I didn't reuse the name to not create confusion. --- mysql-test/main/subselect_sj.result | 6 +- mysql-test/main/subselect_sj_jcl6.result | 8 +- sql/opt_subselect.cc | 103 +++++++++++++++++++---- sql/opt_subselect.h | 8 +- sql/sql_select.cc | 18 +++- sql/sql_select.h | 8 +- 6 files changed, 118 insertions(+), 33 deletions(-) diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result index 13b8a16080f..787ec226bab 100644 --- a/mysql-test/main/subselect_sj.result +++ b/mysql-test/main/subselect_sj.result @@ -2178,10 +2178,10 @@ INSERT INTO t5 VALUES (7,0),(9,0); explain SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t5 index a a 10 NULL 2 Using index; Start temporary +1 PRIMARY t5 index a a 10 NULL 2 Using where; Using index; LooseScan 1 PRIMARY t4 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL b NULL NULL NULL 10 Using where -1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY t2 ref b b 5 test.t5.b 2 Using where; FirstMatch(t5) +1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; Using join buffer (flat, BNL join) SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); a 0 diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result index 54196f62211..be2a55d65d6 100644 --- a/mysql-test/main/subselect_sj_jcl6.result +++ b/mysql-test/main/subselect_sj_jcl6.result @@ -2189,10 +2189,10 @@ INSERT INTO t5 VALUES (7,0),(9,0); explain SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t5 index a a 10 NULL 2 Using index; Start temporary -1 PRIMARY t4 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) -1 PRIMARY t2 ALL b NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join) -1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; End temporary; Using join buffer (incremental, BNL join) +1 PRIMARY t5 index a a 10 NULL 2 Using where; Using index; LooseScan +1 PRIMARY t4 ALL NULL NULL NULL NULL 3 +1 PRIMARY t2 ref b b 5 test.t5.b 2 Using where; FirstMatch(t5) +1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; Using join buffer (flat, BNL join) SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); a 0 diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 6080717e5f5..6e89fe400d3 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -179,7 +179,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - optimize_semijoin_nests() does pre-optimization - during join optimization, the join has one JOIN_TAB (or is it POSITION?) - array, and suffix-based detection is used, see advance_sj_state() + array, and suffix-based detection is used, see optimize_semi_joins() - after join optimization is done, get_best_combination() switches the data-structure to prefix-based, multiple JOIN_TAB ranges format. @@ -2655,7 +2655,7 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables) Do semi-join optimization step after we've added a new tab to join prefix SYNOPSIS - advance_sj_state() + optimize_semi_joins() join The join we're optimizing remaining_tables Tables not in the join prefix new_join_tab Join tab we've just added to the join prefix @@ -2715,9 +2715,9 @@ bool is_multiple_semi_joins(JOIN *join, POSITION *prefix, uint idx, table_map in } -void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, - double *current_record_count, double *current_read_time, - POSITION *loose_scan_pos) +void optimize_semi_joins(JOIN *join, table_map remaining_tables, uint idx, + double *current_record_count, + double *current_read_time, POSITION *loose_scan_pos) { POSITION *pos= join->positions + idx; const JOIN_TAB *new_join_tab= pos->table; @@ -2876,19 +2876,36 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, } } - if ((emb_sj_nest= new_join_tab->emb_sj_nest)) + update_sj_state(join, new_join_tab, idx, remaining_tables); + + pos->prefix_cost.convert_from_cost(*current_read_time); + pos->prefix_record_count= *current_record_count; + pos->dups_producing_tables= dups_producing_tables; +} + + +/* + Update JOIN's semi-join optimization state after the join tab new_tab + has been added into the join prefix. + + @seealso restore_prev_sj_state() does the reverse actoion +*/ + +void update_sj_state(JOIN *join, const JOIN_TAB *new_tab, + uint idx, table_map remaining_tables) +{ + if (TABLE_LIST *emb_sj_nest= new_tab->emb_sj_nest) { join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables; /* Remove the sj_nest if all of its SJ-inner tables are in cur_table_map */ if (!(remaining_tables & - emb_sj_nest->sj_inner_tables & ~new_join_tab->table->map)) + emb_sj_nest->sj_inner_tables & ~new_tab->table->map)) join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; } - - pos->prefix_cost.convert_from_cost(*current_read_time); - pos->prefix_record_count= *current_record_count; - pos->dups_producing_tables= dups_producing_tables; +#ifndef DBUG_OFF + join->dbug_verify_sj_inner_tables(idx + 1); +#endif } @@ -3402,10 +3419,45 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join, return FALSE; } +#ifndef DBUG_OFF +/* + Verify the value of JOIN::cur_sj_inner_tables by recomputing it +*/ +void JOIN::dbug_verify_sj_inner_tables(uint prefix_size) const +{ + table_map cur_map= const_table_map; + table_map nests_entered= 0; + if (emb_sjm_nest) + { + DBUG_ASSERT(cur_sj_inner_tables == 0); + return; + } + + for (uint i= const_tables; i < prefix_size; i++) + { + JOIN_TAB *tab= positions[i].table; + cur_map |= tab->table->map; + if (TABLE_LIST *sj_nest= tab->emb_sj_nest) + { + nests_entered |= sj_nest->sj_inner_tables; + if (!(sj_nest->sj_inner_tables & ~cur_map)) + { + // all nest tables are in the prefix already + nests_entered &= ~sj_nest->sj_inner_tables; + } + } + } + DBUG_ASSERT(nests_entered == cur_sj_inner_tables); +} +#endif /* Remove the last join tab from from join->cur_sj_inner_tables bitmap - we assume remaining_tables doesnt contain @tab. + + @note + remaining_tables contains @tab. + + @seealso update_sj_state() does the reverse */ void restore_prev_sj_state(const table_map remaining_tables, @@ -3419,15 +3471,30 @@ void restore_prev_sj_state(const table_map remaining_tables, tab->join->sjm_lookup_tables &= ~subq_tables; } - if ((emb_sj_nest= tab->emb_sj_nest)) + if (!tab->join->emb_sjm_nest && (emb_sj_nest= tab->emb_sj_nest)) { + table_map subq_tables= emb_sj_nest->sj_inner_tables & + ~tab->join->const_table_map; /* If we're removing the last SJ-inner table, remove the sj-nest */ - if ((remaining_tables & emb_sj_nest->sj_inner_tables) == - (emb_sj_nest->sj_inner_tables & ~tab->table->map)) + if ((remaining_tables & subq_tables) == subq_tables) { + // All non-const tables of the SJ nest are in the remaining_tables. + // we are not in the nest anymore. tab->join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; } + else + { + // Semi-join nest has: + // - a table being removed (not in the prefix) + // - some tables in the prefix. + tab->join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables; + } } + +#ifndef DBUG_OFF + /* positions[idx] has been removed. Verify the state for [0...idx-1] */ + tab->join->dbug_verify_sj_inner_tables(idx); +#endif } @@ -3636,8 +3703,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN; join->best_positions[first].n_sj_tables= sjm->tables; /* - Do what advance_sj_state did: re-run best_access_path for every table - in the [last_inner_table + 1; pos..) range + Do what optimize_semi_joins did: re-run best_access_path for every + table in the [last_inner_table + 1; pos..) range */ double prefix_rec_count; /* Get the prefix record count */ @@ -4842,7 +4909,7 @@ int setup_semijoin_loosescan(JOIN *join) The choice between the strategies is made by the join optimizer (see - advance_sj_state() and fix_semijoin_strategies_for_picked_join_order()). + optimize_semi_joins() and fix_semijoin_strategies_for_picked_join_order()). This function sets up all fields/structures/etc needed for execution except for setup/initialization of semi-join materialization which is done in setup_sj_materialization() (todo: can't we move that to here also?) diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 509fb370fd7..4744c49799a 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -310,9 +310,11 @@ public: }; -void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, - double *current_record_count, double *current_read_time, - POSITION *loose_scan_pos); +void optimize_semi_joins(JOIN *join, table_map remaining_tables, uint idx, + double *current_record_count, + double *current_read_time, POSITION *loose_scan_pos); +void update_sj_state(JOIN *join, const JOIN_TAB *new_tab, + uint idx, table_map remaining_tables); void restore_prev_sj_state(const table_map remaining_tables, const JOIN_TAB *tab, uint idx); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ee834f5d806..87144bd2d7d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7721,6 +7721,10 @@ choose_plan(JOIN *join, table_map join_tables) { choose_initial_table_order(join); } + /* + Note: constant tables are already in the join prefix. We don't + put them into the cur_sj_inner_tables, though. + */ join->cur_sj_inner_tables= 0; if (straight_join) @@ -8023,8 +8027,8 @@ optimize_straight_join(JOIN *join, table_map join_tables) read_time= COST_ADD(read_time, COST_ADD(join->positions[idx].read_time, record_count / (double) TIME_FOR_COMPARE)); - advance_sj_state(join, join_tables, idx, &record_count, &read_time, - &loose_scan_pos); + optimize_semi_joins(join, join_tables, idx, &record_count, &read_time, + &loose_scan_pos); join_tables&= ~(s->table->map); double pushdown_cond_selectivity= 1.0; @@ -8201,6 +8205,12 @@ greedy_search(JOIN *join, /* This has been already checked by best_extension_by_limited_search */ DBUG_ASSERT(!is_interleave_error); + /* + Also, update the semi-join optimization state. Information about the + picked semi-join operation is in best_pos->...picker, but we need to + update the global state in the JOIN object, too. + */ + update_sj_state(join, best_table, idx, remaining_tables); /* find the position of 'best_table' in 'join->best_ref' */ best_idx= idx; @@ -8983,8 +8993,8 @@ best_extension_by_limited_search(JOIN *join, current_record_count / (double) TIME_FOR_COMPARE)); - advance_sj_state(join, remaining_tables, idx, ¤t_record_count, - ¤t_read_time, &loose_scan_pos); + optimize_semi_joins(join, remaining_tables, idx, ¤t_record_count, + ¤t_read_time, &loose_scan_pos); /* Expand only partial plans with lower cost than the best QEP so far */ if (current_read_time >= join->best_read) diff --git a/sql/sql_select.h b/sql/sql_select.h index b37c62a4e51..4591aa7e143 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1259,9 +1259,15 @@ public: Bitmap of inner tables of semi-join nests that have a proper subset of their tables in the current join prefix. That is, of those semi-join nests that have their tables both in and outside of the join prefix. + (Note: tables that are constants but have not been pulled out of semi-join + nests are not considered part of semi-join nests) */ table_map cur_sj_inner_tables; - + +#ifndef DBUG_OFF + void dbug_verify_sj_inner_tables(uint n_positions) const; +#endif + /* We also maintain a stack of join optimization states in * join->positions[] */ /******* Join optimization state members end *******/ From 7c4efab9031c2b08af5caf0e3a2b01a70a3414bf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 May 2022 13:58:31 +0200 Subject: [PATCH 2/8] typo fixed: [[space]] -> [[:space:]] --- scripts/wsrep_sst_rsync.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 1775281e634..994347d6f73 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -842,7 +842,7 @@ EOF fi if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then - if grep -m1 -qE "^$BYPASS_TAG([[space]]+.*)?\$" -- "$MAGIC_FILE"; then + if grep -m1 -qE "^$BYPASS_TAG([[:space:]]+.*)?\$" -- "$MAGIC_FILE"; then readonly WSREP_SST_OPT_BYPASS=1 readonly WSREP_TRANSFER_TYPE='IST' fi From 37ea0778733a21ae603788853ac4fb9a3be9915a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 7 Jun 2022 15:49:41 +0200 Subject: [PATCH 3/8] main.help: flush help tables after modifying them otherwise following tests that crash the server will see them corrupted --- mysql-test/main/help.result | 10 +++++++--- mysql-test/main/help.test | 17 +++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/mysql-test/main/help.result b/mysql-test/main/help.result index 66850e75dc1..a3a236ee89e 100644 --- a/mysql-test/main/help.result +++ b/mysql-test/main/help.result @@ -274,12 +274,16 @@ delete from mysql.help_relation where help_keyword_id=@keyword1_id and help_topi delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topic_id=@topic1_id; delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; -End of 4.1 tests. -DROP TABLE IF EXISTS t1; +flush tables; +# +# End of 4.1 tests. +# CREATE TABLE t1 (i INT); LOCK TABLES t1 WRITE; HELP no_such_topic; name is_it_category UNLOCK TABLES; DROP TABLE t1; -End of 5.1 tests. +# +# End of 5.1 tests. +# diff --git a/mysql-test/main/help.test b/mysql-test/main/help.test index 802f24f80a9..4f1ec5cef70 100644 --- a/mysql-test/main/help.test +++ b/mysql-test/main/help.test @@ -122,25 +122,22 @@ delete from mysql.help_relation where help_keyword_id=@keyword2_id and help_topi delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic3_id; delete from mysql.help_relation where help_keyword_id=@keyword3_id and help_topic_id=@topic4_id; ---echo End of 4.1 tests. +flush tables; +--echo # +--echo # End of 4.1 tests. +--echo # # # Test that we can use HELP even under LOCK TABLES. See bug#9953: # CONVERT_TZ requires mysql.time_zone_name to be locked. # ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings CREATE TABLE t1 (i INT); - LOCK TABLES t1 WRITE; - HELP no_such_topic; - UNLOCK TABLES; - DROP TABLE t1; - ---echo End of 5.1 tests. +--echo # +--echo # End of 5.1 tests. +--echo # From 960f0344a21af4bd8d422b9bfb9a617947d7541d Mon Sep 17 00:00:00 2001 From: chansuke Date: Tue, 7 Jun 2022 22:33:37 +0900 Subject: [PATCH 4/8] MDEV-25273: fix typo (s/strucures/structures/) --- sql/share/errmsg-utf8.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 300ec1eaa46..b05fa5e5412 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7637,7 +7637,7 @@ ER_JSON_SYNTAX ER_JSON_ESCAPING eng "Incorrect escaping in JSON text in argument %d to function '%s' at position %d" ER_JSON_DEPTH - eng "Limit of %d on JSON nested strucures depth is reached in argument %d to function '%s' at position %d" + eng "Limit of %d on JSON nested structures depth is reached in argument %d to function '%s' at position %d" ER_JSON_PATH_EOS eng "Unexpected end of JSON path in argument %d to function '%s'" ER_JSON_PATH_SYNTAX From 44ab6cba762e23a992e7c3bfd8f4319e56e08fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 8 Jun 2022 14:23:21 +0300 Subject: [PATCH 5/8] Cleanup: Remove unused error code DB_FORCED_ABORT MariaDB never supported this form of preemption via high-priority transactions. This error code shold not have been added in the first place, in commit 2e814d4702d71a04388386a9f591d14a35980bfe. --- storage/innobase/include/db0err.h | 5 +---- storage/innobase/ut/ut0ut.cc | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index f70a65890c9..037821a89e7 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2022, 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 @@ -148,9 +148,6 @@ enum dberr_t { DB_IO_PARTIAL_FAILED, /*!< Partial IO request failed */ - DB_FORCED_ABORT, /*!< Transaction was forced to rollback - by a higher priority transaction */ - DB_TABLE_CORRUPT, /*!< Table/clustered index is corrupted */ diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 7f7be193175..8a4e1151101 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +Copyright (c) 2017, 2022, 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 @@ -486,9 +486,6 @@ ut_strerr( return("Table is encrypted but decrypt failed."); case DB_IO_PARTIAL_FAILED: return("Partial IO failed"); - case DB_FORCED_ABORT: - return("Transaction aborted by another higher priority " - "transaction"); case DB_COMPUTE_VALUE_FAILED: return("Compute generated column failed"); case DB_NO_FK_ON_S_BASE_COL: From 9c207c88c1411d1e538e8412182311de63757771 Mon Sep 17 00:00:00 2001 From: GuiXiaoDi Date: Fri, 3 Jun 2022 15:08:46 +0800 Subject: [PATCH 6/8] mysql.server.sh fix for non-Red Hat platforms The else condition is meant to be here to define the functions if the Red Hat include file isn't there. Fixes: commit 467011bcac3b3f42ae6f21dde8d88e78708b21d1 / MDEV-26614 RedHat -> Red Hat by Daniel Black --- support-files/mysql.server.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 7f034601539..54bd9463f61 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -9,7 +9,7 @@ # When this is done the mysql server will be started when the machine is # started and shut down when the systems goes down. -# Comments to support chkconfig on RedHat Linux +# Comments to support chkconfig on Red Hat Linux # chkconfig: 2345 64 36 # description: A very fast and reliable SQL database engine. @@ -52,7 +52,7 @@ datadir= # Negative numbers mean to wait indefinitely service_startup_timeout=900 -# Lock directory for RedHat / SuSE. +# Lock directory for Red Hat / SuSE. lockdir='/var/lock/subsys' lock_file_path="$lockdir/mysql" @@ -91,7 +91,7 @@ datadir_set= # # Use LSB init script functions for printing messages, if possible -# Include non-LSB RedHat init functions to make systemctl redirect work +# Include non-LSB Red Hat init functions to make systemctl redirect work init_functions="/etc/init.d/functions" lsb_functions="/lib/lsb/init-functions" if test -f $lsb_functions; then @@ -100,6 +100,7 @@ fi if test -f $init_functions; then . $init_functions +else log_success_msg() { echo " SUCCESS! $@" @@ -309,7 +310,7 @@ case "$mode" in $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" "$@" & wait_for_ready; return_value=$? - # Make lock for RedHat / SuSE + # Make lock for Red Hat / SuSE if test -w "$lockdir" then touch "$lock_file_path" @@ -339,7 +340,7 @@ case "$mode" in rm "$mysqld_pid_file_path" fi - # Delete lock for RedHat / SuSE + # Delete lock for Red Hat / SuSE if test -f "$lock_file_path" then rm -f "$lock_file_path" From 2cd1edfc2176649cda412b2ff4f1075ad23448ba Mon Sep 17 00:00:00 2001 From: Daniel Lewart Date: Thu, 9 Jun 2022 13:20:37 +1000 Subject: [PATCH 7/8] MDEV-25577 mariadb-tzinfo-to-sql generates superfluous warnings The zoneinfo directory is littered with non-timezone information files. These frequently contain extensions, not present in real timezone files. Alo leapseconds is frequently there and is not a timezone file. --- sql/tztime.cc | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/sql/tztime.cc b/sql/tztime.cc index dfd0301037f..ec9e68ee66d 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2470,15 +2470,6 @@ MEM_ROOT tz_storage; char fullname[FN_REFLEN + 1]; char *root_name_end; -/* - known file types that exist in the zoneinfo directory that are safe to - silently skip -*/ -const char *known_extensions[]= { - ".tab", - NullS -}; - /* Recursively scan zoneinfo directory and print all found time zone @@ -2575,20 +2566,19 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level, uint verbose) else { /* - Some systems (like debian, opensuse etc) have description - files (.tab). We skip these silently if verbose is > 0 + Some systems (like Debian, openSUSE, etc) have non-timezone files: + * iso3166.tab + * leap-seconds.list + * leapseconds + * tzdata.zi + * zone.tab + * zone1970.tab + We skip these silently unless verbose > 0. */ const char *current_ext= fn_ext(fullname); - my_bool known_ext= 0; + my_bool known_ext= strlen(current_ext) || + !strcmp(my_basename(fullname), "leapseconds"); - for (const char **ext= known_extensions ; *ext ; ext++) - { - if (!strcmp(*ext, current_ext)) - { - known_ext= 1; - break; - } - } if (verbose > 0 || !known_ext) { fflush(stdout); From 98293130c34cfd39bf2e8c904923abe3942d23be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 9 Jun 2022 10:57:28 +0300 Subject: [PATCH 8/8] MDEV-28779: ALTER TABLE IMPORT TABLESPACE corrupts an encrypted table PageConverter::update_header(): Remove an unnecessary write. The field that was originally called FIL_PAGE_FILE_FLUSH_LSN only made sense for the first page of the system tablespace (initially, for the first page of each file of the system tablespace). It never had any meaning for .ibd files, and it lost its original meaning in MariaDB Server 10.8.1 when commit b07920b634f455c39e3650c6163bec2a8ce0ffe0 (MDEV-27199) removed the ability to start without ib_logfile0. If the most significant 32 bits of the LSN are nonzero, this unnecessary write would write the wrong encryption key identifier to the page. The first page of any file is never encrypted, so normally those bytes should be 0 for any .ibd file. --- mysql-test/suite/mariabackup/huge_lsn.result | 10 +++++++++- mysql-test/suite/mariabackup/huge_lsn.test | 18 +++++++++++++++++- storage/innobase/row/row0import.cc | 6 +----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/mariabackup/huge_lsn.result b/mysql-test/suite/mariabackup/huge_lsn.result index 61ca3400721..2225a958756 100644 --- a/mysql-test/suite/mariabackup/huge_lsn.result +++ b/mysql-test/suite/mariabackup/huge_lsn.result @@ -2,7 +2,7 @@ # MDEV-13416 mariabackup fails with EFAULT "Bad Address" # FOUND 1 /InnoDB: New log files created, LSN=175964\d{8}/ in mysqld.1.err -CREATE TABLE t(i INT) ENGINE INNODB; +CREATE TABLE t(i INT) ENGINE=INNODB ENCRYPTED=YES; INSERT INTO t VALUES(1); # xtrabackup backup SET GLOBAL innodb_flush_log_at_trx_commit=1; @@ -15,6 +15,14 @@ INSERT INTO t VALUES(2); SELECT * FROM t; i 1 +FLUSH TABLE t FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t DISCARD TABLESPACE; +ALTER TABLE t IMPORT TABLESPACE; +FLUSH TABLE t FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t DISCARD TABLESPACE; +ALTER TABLE t IMPORT TABLESPACE; DROP TABLE t; # shutdown server # remove datadir diff --git a/mysql-test/suite/mariabackup/huge_lsn.test b/mysql-test/suite/mariabackup/huge_lsn.test index 3349ef40df8..55978071be3 100644 --- a/mysql-test/suite/mariabackup/huge_lsn.test +++ b/mysql-test/suite/mariabackup/huge_lsn.test @@ -40,7 +40,7 @@ let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; --let SEARCH_PATTERN= InnoDB: New log files created, LSN=175964\d{8} --source include/search_pattern_in_file.inc -CREATE TABLE t(i INT) ENGINE INNODB; +CREATE TABLE t(i INT) ENGINE=INNODB ENCRYPTED=YES; INSERT INTO t VALUES(1); echo # xtrabackup backup; @@ -56,6 +56,22 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir; --source include/restart_and_restore.inc --enable_result_log SELECT * FROM t; +FLUSH TABLE t FOR EXPORT; +copy_file $_datadir/test/t.ibd $_datadir/test/t_copy.ibd; +copy_file $_datadir/test/t.cfg $_datadir/test/t_copy.cfg; +UNLOCK TABLES; +ALTER TABLE t DISCARD TABLESPACE; +move_file $_datadir/test/t_copy.ibd $_datadir/test/t.ibd; +move_file $_datadir/test/t_copy.cfg $_datadir/test/t.cfg; +ALTER TABLE t IMPORT TABLESPACE; +FLUSH TABLE t FOR EXPORT; +copy_file $_datadir/test/t.ibd $_datadir/test/t_copy.ibd; +copy_file $_datadir/test/t.cfg $_datadir/test/t_copy.cfg; +UNLOCK TABLES; +ALTER TABLE t DISCARD TABLESPACE; +move_file $_datadir/test/t_copy.ibd $_datadir/test/t.ibd; +move_file $_datadir/test/t_copy.cfg $_datadir/test/t.cfg; +ALTER TABLE t IMPORT TABLESPACE; DROP TABLE t; rmdir $targetdir; let $targetdir= $targetdir_old; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 885a43bb2f8..db4c22b4969 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, 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 @@ -1996,10 +1996,6 @@ PageConverter::update_header( ib::warn() << "Space id check in the header failed: ignored"; } - mach_write_to_8( - get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, - m_current_lsn); - /* Write back the adjusted flags. */ mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + get_frame(block), m_space_flags);