Commit 003095e8 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-26936 Recovery crash on rolling back DELETE FROM SYS_INDEXES

row_undo_mod_clust_low(): If we are in recovery and rolling back
a DELETE operation on the SYS_INDEXES table, and the
SYS_INDEXES.NAME starts with the magic byte 0xff
that identifies uncommitted ADD INDEX stubs, we must not
try to evict the table definition because such index stubs
would be skipped by dict_load_indexes() anyway.
parent 37a4ea3f
......@@ -189,3 +189,36 @@ disconnect con1;
DROP TABLE t1;
SET DEBUG_SYNC = 'RESET';
SET SQL_MODE=DEFAULT;
#
# MDEV-26936 Recovery crash on rolling back DELETE FROM SYS_INDEXES
#
CREATE TABLE t1(a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1,1);
connect ddl, localhost, root;
SET DEBUG_SYNC = 'row_merge_after_scan SIGNAL scanned WAIT_FOR commit';
SET DEBUG_SYNC = 'before_commit_rollback_inplace SIGNAL c WAIT_FOR ever';
ALTER TABLE t1 ADD UNIQUE INDEX(b), ALGORITHM=INPLACE;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR scanned';
BEGIN;
INSERT INTO t1 VALUES(2,1);
SET DEBUG_SYNC = 'now SIGNAL commit';
SET DEBUG_SYNC = 'now WAIT_FOR c';
SET GLOBAL innodb_fil_make_page_dirty_debug=0;
# Kill the server
disconnect ddl;
# restart
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SELECT * FROM t1;
a b
1 1
DROP TABLE t1;
......@@ -4,6 +4,7 @@
--source include/not_embedded.inc
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/not_crashrep.inc
--disable_query_log
......@@ -195,3 +196,33 @@ disconnect con1;
DROP TABLE t1;
SET DEBUG_SYNC = 'RESET';
SET SQL_MODE=DEFAULT;
--echo #
--echo # MDEV-26936 Recovery crash on rolling back DELETE FROM SYS_INDEXES
--echo #
CREATE TABLE t1(a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1,1);
connect ddl, localhost, root;
SET DEBUG_SYNC = 'row_merge_after_scan SIGNAL scanned WAIT_FOR commit';
SET DEBUG_SYNC = 'before_commit_rollback_inplace SIGNAL c WAIT_FOR ever';
send ALTER TABLE t1 ADD UNIQUE INDEX(b), ALGORITHM=INPLACE;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR scanned';
BEGIN;
INSERT INTO t1 VALUES(2,1);
SET DEBUG_SYNC = 'now SIGNAL commit';
SET DEBUG_SYNC = 'now WAIT_FOR c';
# Make all pending changes durable for recovery.
SET GLOBAL innodb_fil_make_page_dirty_debug=0;
--source include/kill_mysqld.inc
disconnect ddl;
--source include/start_mysqld.inc
CHECK TABLE t1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
......@@ -8764,6 +8764,7 @@ inline bool rollback_inplace_alter_table(Alter_inplace_info *ha_alter_info,
ut_d(dict_table_check_for_dup_indexes(ctx->old_table, CHECK_ABORTED_OK));
}
DEBUG_SYNC(ctx->trx->mysql_thd, "before_commit_rollback_inplace");
commit_unlock_and_unlink(ctx->trx);
if (fts_exist)
purge_sys.resume_FTS();
......
......@@ -173,6 +173,16 @@ row_undo_mod_clust_low(
case DICT_INDEXES_ID:
if (node->trx != trx_roll_crash_recv_trx) {
break;
} else if (node->rec_type == TRX_UNDO_DEL_MARK_REC
&& btr_cur_get_rec(btr_cur)
[8 + 8 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN]
== static_cast<byte>(*TEMP_INDEX_PREFIX_STR)) {
/* We are rolling back the DELETE of metadata
for a failed ADD INDEX operation. This does
not affect any cached table definition,
because we are filtering out such indexes in
dict_load_indexes(). */
break;
}
/* fall through */
case DICT_COLUMNS_ID:
......
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