From 194bb9d4ca3bc91a22379722775dadd05864685b Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sun, 18 Jan 2026 01:58:23 +0400 Subject: [PATCH] MDEV-37795 - MariaDB start up spits DDL_LOG: Got error 1033 innodb_fts.crash_recovery,release fails sporadically. In release build it silently disables sync points, which allows server to crash at aribitrary point of DDL, specifically when .frm file is created but not yet written. Subsequent attempt to open such table at recovery (needed to obtain number of high-level indexes) leads to OPEN_FRM_CORRUPTED error rather than something like "file not found" (which is ignored by recovery). Emitted errors were not handler by mtr. Silently ignore newly created corrupt .frm during recovery. High-level indexes were most probably not created at this point. It is still probable that .frm got corrupted after high-level indexes were created. In this case recovery won't be able to handle stale high-level indexes and they will be preserved. This regression was introduced by "d50663198c0 DDL recovery for high-level indexes". --- mysql-test/suite/atomic/frm.result | 21 +++++++++++++++++++++ mysql-test/suite/atomic/frm.test | 28 ++++++++++++++++++++++++++++ sql/ddl_log.cc | 13 +++++++++++-- sql/discover.cc | 1 + 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/atomic/frm.result create mode 100644 mysql-test/suite/atomic/frm.test diff --git a/mysql-test/suite/atomic/frm.result b/mysql-test/suite/atomic/frm.result new file mode 100644 index 0000000000000..578904ba8ce6e --- /dev/null +++ b/mysql-test/suite/atomic/frm.result @@ -0,0 +1,21 @@ +# +# MDEV-37795 - MariaDB start up spits DDL_LOG: Got error 1033 +# +connect ddl1, localhost, root; +CREATE TABLE t1(v VECTOR(5) NOT NULL, VECTOR INDEX(v)); +SET debug_sync='writefile_after_create_before_write SIGNAL ready1 WAIT_FOR ever'; +ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=COPY; +connect ddl2, localhost, root; +SET debug_sync='writefile_after_create_before_write SIGNAL ready2 WAIT_FOR ever'; +CREATE TABLE t2(v VECTOR(5) NOT NULL, VECTOR INDEX(v)); +connection default; +SET debug_sync='now WAIT_FOR ready1'; +SET debug_sync='now WAIT_FOR ready2'; +# restart +DROP TABLE t1; +DROP TABLE t2; +ERROR 42S02: Unknown table 'test.t2' +SET debug_sync='RESET'; +disconnect ddl1; +disconnect ddl2; +db.opt diff --git a/mysql-test/suite/atomic/frm.test b/mysql-test/suite/atomic/frm.test new file mode 100644 index 0000000000000..7be0c37741bf6 --- /dev/null +++ b/mysql-test/suite/atomic/frm.test @@ -0,0 +1,28 @@ +source include/have_debug_sync.inc; + +--echo # +--echo # MDEV-37795 - MariaDB start up spits DDL_LOG: Got error 1033 +--echo # +connect(ddl1, localhost, root); +CREATE TABLE t1(v VECTOR(5) NOT NULL, VECTOR INDEX(v)); +SET debug_sync='writefile_after_create_before_write SIGNAL ready1 WAIT_FOR ever'; +send ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=COPY; + +connect(ddl2, localhost, root); +SET debug_sync='writefile_after_create_before_write SIGNAL ready2 WAIT_FOR ever'; +send CREATE TABLE t2(v VECTOR(5) NOT NULL, VECTOR INDEX(v)); + +connection default; +SET debug_sync='now WAIT_FOR ready1'; +SET debug_sync='now WAIT_FOR ready2'; +let $shutdown_timeout=0; +source include/restart_mysqld.inc; + +DROP TABLE t1; +error ER_BAD_TABLE_ERROR; +DROP TABLE t2; +SET debug_sync='RESET'; +disconnect ddl1; +disconnect ddl2; +let $datadir=`select @@datadir`; +list_files $datadir/test; diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc index df402f4bb0fdc..423c526ad1a17 100644 --- a/sql/ddl_log.cc +++ b/sql/ddl_log.cc @@ -919,9 +919,11 @@ class ddl_log_error_handler : public Internal_error_handler int unhandled_errors; int first_error; bool only_ignore_non_existing_errors; + bool ignore_corrupt_frm_error; ddl_log_error_handler() : handled_errors(0), unhandled_errors(0), - first_error(0), only_ignore_non_existing_errors(0) + first_error(0), only_ignore_non_existing_errors(0), + ignore_corrupt_frm_error(false) {} bool handle_condition(THD *, @@ -935,7 +937,8 @@ class ddl_log_error_handler : public Internal_error_handler if (non_existing_table_error(sql_errno) || (!only_ignore_non_existing_errors && (sql_errno == EE_LINK || - sql_errno == EE_DELETE || sql_errno == ER_TRG_NO_DEFINER))) + sql_errno == EE_DELETE || sql_errno == ER_TRG_NO_DEFINER)) || + (ignore_corrupt_frm_error && sql_errno == ER_NOT_FORM_FILE)) { handled_errors++; return TRUE; @@ -1799,7 +1802,11 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root, if (ddl_log_entry->flags == 0) { if (hton) + { + no_such_table_handler.ignore_corrupt_frm_error= true; error= execute_drop_table(thd, hton, &db, &table, path.str); + no_such_table_handler.ignore_corrupt_frm_error= false; + } else error= ha_delete_table_force(thd, path.str, &db, &table); } @@ -2273,9 +2280,11 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root, */ if (likely(hton)) { + no_such_table_handler.ignore_corrupt_frm_error= true; error= execute_drop_table(thd, hton, &ddl_log_entry->from_db, &ddl_log_entry->from_name, ddl_log_entry->tmp_name.str); + no_such_table_handler.ignore_corrupt_frm_error= false; } (void) update_phase(entry_pos, DDL_ALTER_TABLE_PHASE_INIT); } diff --git a/sql/discover.cc b/sql/discover.cc index 4295bd6956281..3118bdd7853bd 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -137,6 +137,7 @@ int writefile(const char *path, const char *db, const char *table, } else { + DEBUG_SYNC(current_thd, "writefile_after_create_before_write"); error= (int)mysql_file_write(file, data, len, MYF(MY_WME | MY_NABP)); if (!error && !tmp_table && opt_sync_frm)