Commit e1c953ef authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-25989 Crash (or hang) on startup after restoring backup

If an ALTER TABLE that affected a table with FULLTEXT INDEX was
in progress while a backup was made, InnoDB would crash or hang
during the first startup after restoring the backup,
while trying to drop the #sql-alter- table for the DDL operation.

drop_garbage_tables_after_restore(): Invoke dict_sys.unlock()
before invoking the FTS functions. Also, invoke purge_sys.stop_FTS()
in debug builds to silence debug assertions. (Purge is not yet
running at this point.)
parent 367c75c0
# xtrabackup backup
CREATE TABLE t1(i int) ENGINE=InnoDB;
INSERT into t1 values(1);
CREATE TABLE t1(i int, t text, fulltext index(t)) ENGINE=InnoDB;
INSERT into t1 values(1,'foo');
connect con2, localhost, root,,;
connection con2;
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit' ;
SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 FORCE, algorithm=COPY;|
SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 DROP t, algorithm=COPY;|
connection default;
connection con2;
SET debug_sync='RESET';
......@@ -15,11 +15,10 @@ connection default;
# remove datadir
# xtrabackup move back
# restart
SELECT COUNT(*) AS expect_0 FROM INFORMATION_SCHEMA.innodb_sys_tablespaces WHERE name like '%/#sql%';
expect_0
0
SELECT * FROM t1;
i
1
i t
1 foo
DROP TABLE t1;
SELECT * FROM INFORMATION_SCHEMA.innodb_sys_tablespaces WHERE name like '%/#sql%' or name like 'test/%';
SPACE NAME FLAG ROW_FORMAT PAGE_SIZE FILENAME FS_BLOCK_SIZE FILE_SIZE ALLOCATED_SIZE
# restart
......@@ -7,14 +7,14 @@
echo # xtrabackup backup;
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
CREATE TABLE t1(i int) ENGINE=InnoDB;
INSERT into t1 values(1);
CREATE TABLE t1(i int, t text, fulltext index(t)) ENGINE=InnoDB;
INSERT into t1 values(1,'foo');
connect con2, localhost, root,,;
connection con2;
SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit' ;
DELIMITER |;
send SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 FORCE, algorithm=COPY;|
send SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 DROP t, algorithm=COPY;|
DELIMITER ;|
connection default;
......@@ -53,9 +53,9 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir;
--enable_result_log
# Check there are no temp tablespaces in sys_tablespaces, after backup
SELECT COUNT(*) AS expect_0 FROM INFORMATION_SCHEMA.innodb_sys_tablespaces WHERE name like '%/#sql%';
SELECT * FROM t1;
DROP TABLE t1;
SELECT * FROM INFORMATION_SCHEMA.innodb_sys_tablespaces WHERE name like '%/#sql%' or name like 'test/%';
# Restart once again to clear first_start_after_backup flag
# This is to catch potential warnings, since "missing file" for #sql is suppressed
......
......@@ -1969,6 +1969,9 @@ static void drop_garbage_tables_after_restore()
mtr_t mtr;
trx_t *trx= trx_create();
ut_ad(!purge_sys.enabled());
ut_d(purge_sys.stop_FTS());
mtr.start();
btr_pcur_open_at_index_side(true, dict_sys.sys_tables->indexes.start,
BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
......@@ -2028,8 +2031,10 @@ static void drop_garbage_tables_after_restore()
if (err == DB_SUCCESS &&
(table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS)))
{
dict_sys.unlock();
fts_optimize_remove_table(table);
err= fts_lock_tables(trx, *table);
dict_sys.lock(SRW_LOCK_CALL);
}
table->release();
......@@ -2058,6 +2063,7 @@ static void drop_garbage_tables_after_restore()
btr_pcur_close(&pcur);
mtr.commit();
trx->free();
ut_d(purge_sys.resume_FTS());
}
static void innodb_ddl_recovery_done(handlerton*)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment