From 02a313dc5637fae7a5de037ea43df4cd508908fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Jun 2022 12:29:30 +0300 Subject: [PATCH 1/4] MDEV-18976 fixup: encryption.innodb-redo-nokeys This test failure is similar to encryption.innodb-redo-badkey, which was fixed in commit 0f0a45b2dc9fe3c54ca9d146db8068b50fc97138. --- mysql-test/suite/encryption/r/innodb-redo-nokeys.result | 3 +++ mysql-test/suite/encryption/t/innodb-redo-nokeys.test | 3 +++ 2 files changed, 6 insertions(+) diff --git a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result index 007fe21ed69..88b5c583f61 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result +++ b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result @@ -5,6 +5,9 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error\\."); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); call mtr.add_suppression("InnoDB: Cannot apply log to \\[page id: space=[1-9][0-9]*, page number=0\\] of corrupted file '.*test.t[1-5]\\.ibd'"); +call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); +call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); +call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt SET GLOBAL innodb_file_per_table = ON; create table t1(a int not null primary key auto_increment, c char(200), b blob, index(b(10))) engine=innodb row_format=compressed encrypted=yes encryption_key_id=20; diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test index 9deae2f7acb..866b02b58c0 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test +++ b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test @@ -10,6 +10,9 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error\\."); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); call mtr.add_suppression("InnoDB: Cannot apply log to \\[page id: space=[1-9][0-9]*, page number=0\\] of corrupted file '.*test.t[1-5]\\.ibd'"); +call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); +call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); +call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt -- source include/restart_mysqld.inc From 5e40934d24d7704ba8ed4899f4e41b9fc120731a Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 28 Jun 2022 15:57:41 +0300 Subject: [PATCH 2/4] MDEV-28897 Wrong table.get_ref_count() upon concurrent truncate and backup stage operation The issue was that flush_tables() didn't take a MDL lock on cached TABLE_SHARE before calling open_table() to do a HA_EXTRA_FLUSH call. Most engines seams to have no issue with it, but apparantly this conflicts with InnoDB in 10.6 when using TRUNCATE Fixed by taking a MDL lock before trying to open the table in flush_tables(). There is no test case as it hard to repeat the scheduling that causes the error. I did run the test case in MDEV-28897 to verify that the bug is fixed. --- sql/sql_base.cc | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed21f5ab3e2..1dd57cc319a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -515,7 +515,7 @@ public: Sql_condition ** cond_hdl) { *cond_hdl= NULL; - if (sql_errno == ER_OPEN_AS_READONLY) + if (sql_errno == ER_OPEN_AS_READONLY || sql_errno == ER_LOCK_WAIT_TIMEOUT) { handled_errors++; return TRUE; @@ -600,24 +600,43 @@ bool flush_tables(THD *thd, flush_tables_type flag) else { /* - HA_OPEN_FOR_FLUSH is used to allow us to open the table even if - TABLE_SHARE::incompatible_version is set. It also will tell - SEQUENCE engine that we don't have to read the sequence information - (which may cause deadlocks with concurrently running ALTER TABLE or - ALTER SEQUENCE) as we will close the table at once. + No free TABLE instances available. We have to open a new one. + + Try to take a MDL lock to ensure we can open a new table instance. + If the lock fails, it means that some DDL operation or flush tables + with read lock is ongoing. + In this case we cannot sending the HA_EXTRA_FLUSH signal. */ - if (!open_table_from_share(thd, share, &empty_clex_str, - HA_OPEN_KEYFILE, 0, - HA_OPEN_FOR_ALTER | HA_OPEN_FOR_FLUSH, - tmp_table, FALSE, - NULL)) + + MDL_request mdl_request; + MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, + share->db.str, + share->table_name.str, + MDL_SHARED, MDL_EXPLICIT); + + if (!thd->mdl_context.acquire_lock(&mdl_request, 0)) { - (void) tmp_table->file->extra(HA_EXTRA_FLUSH); /* - We don't put the table into the TDC as the table was not fully - opened (we didn't open triggers) + HA_OPEN_FOR_FLUSH is used to allow us to open the table even if + TABLE_SHARE::incompatible_version is set. It also will tell + SEQUENCE engine that we don't have to read the sequence information + (which may cause deadlocks with concurrently running ALTER TABLE or + ALTER SEQUENCE) as we will close the table at once. */ - closefrm(tmp_table); + if (!open_table_from_share(thd, share, &empty_clex_str, + HA_OPEN_KEYFILE, 0, + HA_OPEN_FOR_ALTER | HA_OPEN_FOR_FLUSH, + tmp_table, FALSE, + NULL)) + { + (void) tmp_table->file->extra(HA_EXTRA_FLUSH); + /* + We don't put the table into the TDC as the table was not fully + opened (we didn't open triggers) + */ + closefrm(tmp_table); + } + thd->mdl_context.release_lock(mdl_request.ticket); } } tdc_release_share(share); From 2fa3ada07202bfd8764cff0bf2e5bbf8a805f8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Jun 2022 20:58:45 +0300 Subject: [PATCH 3/4] Fix a sporadic failure of main.backup_locks Ever since commit 9608773f75e2ca21491ef6825c3616cdc96d1ca5 the InnoDB persistent statistics are enabled on all InnoDB tables by default. We must filter out any output that indicates that the statistics tables are being internally accessed by InnoDB. --- mysql-test/main/backup_locks.result | 2 +- mysql-test/main/backup_locks.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/backup_locks.result b/mysql-test/main/backup_locks.result index 2942231678e..31aed5f3cc8 100644 --- a/mysql-test/main/backup_locks.result +++ b/mysql-test/main/backup_locks.result @@ -32,7 +32,7 @@ a connection con1; drop table t1; connection default; -SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info where table_name not like "innodb_%"; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME MDL_SHARED_HIGH_PRIO Table metadata lock test t1 MDL_INTENTION_EXCLUSIVE Schema metadata lock test diff --git a/mysql-test/main/backup_locks.test b/mysql-test/main/backup_locks.test index 02313186bec..7dc97d7932d 100644 --- a/mysql-test/main/backup_locks.test +++ b/mysql-test/main/backup_locks.test @@ -39,7 +39,7 @@ let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock"; --source include/wait_condition.inc -SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info where table_name not like "innodb_%"; --error ER_LOCK_DEADLOCK select * from t1; backup unlock; From c1e3fc0e0dcbc8275b46916fb5247e9e7635d072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Jun 2022 15:48:44 +0300 Subject: [PATCH 4/4] MDEV-28977: mariabackup.huge_lsn,strict_full_crc32 fails in 10.8 recv_sys_t::recover_deferred(): Hold the exclusive page latch until the tablespace has been set up. Otherwise, the write of the page may be lost due to non-existent tablespace. This race only affects the recovery of the first page in a newly created tablespace. This race condition was introduced in MDEV-24626. --- storage/innobase/log/log0recv.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index fa3b268cf2f..8d28eacb3ee 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -946,17 +946,13 @@ bool recv_sys_t::recover_deferred(recv_sys_t::map::iterator &p, (fil_space_t::zip_size(flags), page), size); if (!space) - { - block->page.lock.x_unlock(); - goto fail; - } + goto release_and_fail; space->free_limit= fsp_header_get_field(page, FSP_FREE_LIMIT); space->free_len= flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + page); - block->page.lock.x_unlock(); fil_node_t *node= UT_LIST_GET_FIRST(space->chain); node->deferred= true; if (!space->acquire()) - goto fail; + goto release_and_fail; fil_names_dirty(space); const bool is_compressed= fil_space_t::is_compressed(flags); #ifdef _WIN32 @@ -973,14 +969,16 @@ bool recv_sys_t::recover_deferred(recv_sys_t::map::iterator &p, ~4095ULL, is_sparse)) { space->release(); - goto fail; + goto release_and_fail; } node->deferred= false; space->release(); it->second.space= space; + block->page.lock.x_unlock(); return false; } + release_and_fail: block->page.lock.x_unlock(); }