Commit 376bf4ed authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-19241 InnoDB fails to write MLOG_INDEX_LOAD upon completing ALTER TABLE

Similar to what was done in commit aa3f7a10
for FULLTEXT INDEX, we must ensure that MLOG_INDEX_LOAD records will always
be written if redo logging was disabled.

row_merge_build_indexes(): Invoke row_merge_write_redo() also when
online operation is not being executed or an error occurs.
In case of an error, invoke flush_observer->interrupted() so that
the pages will not be flushed but merely evicted from the buffer pool.
Before resuming redo logging, it is crucial for the correctness of
mariabackup and InnoDB crash recovery to flush or evict all affected pages
and to write MLOG_INDEX_LOAD records.
parent bc8d173b
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
# #
CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,2); INSERT INTO t1 VALUES (1,2);
ALTER TABLE t1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE; ALTER TABLE t1 ADD PRIMARY KEY(a), LOCK=SHARED, ALGORITHM=INPLACE;
ALTER TABLE t1 DROP INDEX b, ADD INDEX (b); ALTER TABLE t1 DROP INDEX b, ADD INDEX (b), LOCK=SHARED;
# Kill the server # Kill the server
FOUND 1 /scan .*: multi-log rec MLOG_FILE_CREATE2.*page .*:0/ in mysqld.1.err FOUND 2 /scan \d+: multi-log rec MLOG_FILE_CREATE2 len \d+ page \d+:0/ in mysqld.1.err
FOUND 1 /scan .*: log rec MLOG_INDEX_LOAD/ in mysqld.1.err FOUND 3 /scan \d+: log rec MLOG_INDEX_LOAD/ in mysqld.1.err
CHECK TABLE t1; CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
......
...@@ -19,9 +19,9 @@ CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB; ...@@ -19,9 +19,9 @@ CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB;
# MLOG_INDEX_LOAD will not be emitted for empty tables. Insert a row. # MLOG_INDEX_LOAD will not be emitted for empty tables. Insert a row.
INSERT INTO t1 VALUES (1,2); INSERT INTO t1 VALUES (1,2);
# We should get two MLOG_INDEX_LOAD for this. # We should get two MLOG_INDEX_LOAD for this.
ALTER TABLE t1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE; ALTER TABLE t1 ADD PRIMARY KEY(a), LOCK=SHARED, ALGORITHM=INPLACE;
# And one MLOG_INDEX_LOAD for this. # And one MLOG_INDEX_LOAD for this.
ALTER TABLE t1 DROP INDEX b, ADD INDEX (b); ALTER TABLE t1 DROP INDEX b, ADD INDEX (b), LOCK=SHARED;
--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1; --let CLEANUP_IF_CHECKPOINT=DROP TABLE t1;
--source include/no_checkpoint_end.inc --source include/no_checkpoint_end.inc
...@@ -32,10 +32,10 @@ ALTER TABLE t1 DROP INDEX b, ADD INDEX (b); ...@@ -32,10 +32,10 @@ ALTER TABLE t1 DROP INDEX b, ADD INDEX (b);
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err;
let SEARCH_ABORT=NOT FOUND; let SEARCH_ABORT=NOT FOUND;
# ensure that we have exactly 2 records there. # ensure that we have exactly 2 records there.
let SEARCH_PATTERN=scan .*: multi-log rec MLOG_FILE_CREATE2.*page .*:0; let SEARCH_PATTERN=scan \d+: multi-log rec MLOG_FILE_CREATE2 len \d+ page \d+:0;
--source include/search_pattern_in_file.inc --source include/search_pattern_in_file.inc
# ensure that we have exactly 3 records there. # ensure that we have exactly 3 records there.
let SEARCH_PATTERN=scan .*: log rec MLOG_INDEX_LOAD; let SEARCH_PATTERN=scan \d+: log rec MLOG_INDEX_LOAD;
--source include/search_pattern_in_file.inc --source include/search_pattern_in_file.inc
CHECK TABLE t1; CHECK TABLE t1;
......
...@@ -4893,23 +4893,28 @@ row_merge_build_indexes( ...@@ -4893,23 +4893,28 @@ row_merge_build_indexes(
if (indexes[i]->type & DICT_FTS) { if (indexes[i]->type & DICT_FTS) {
row_fts_psort_info_destroy(psort_info, merge_info); row_fts_psort_info_destroy(psort_info, merge_info);
fts_psort_initiated = false; fts_psort_initiated = false;
} else if (error != DB_SUCCESS || !online) { } else if (dict_index_is_spatial(indexes[i])) {
/* Do not apply any online log. */ /* We never disable redo logging for
creating SPATIAL INDEX. Avoid writing any
unnecessary MLOG_INDEX_LOAD record. */
} else if (old_table != new_table) { } else if (old_table != new_table) {
ut_ad(!sort_idx->online_log); ut_ad(!sort_idx->online_log);
ut_ad(sort_idx->online_status ut_ad(sort_idx->online_status
== ONLINE_INDEX_COMPLETE); == ONLINE_INDEX_COMPLETE);
} else {
if (dict_index_is_spatial(indexes[i])) {
/* We never disable redo logging for
creating SPATIAL INDEX. Avoid writing any
unnecessary MLOG_INDEX_LOAD record. */
} else if (FlushObserver* flush_observer = } else if (FlushObserver* flush_observer =
trx->get_flush_observer()) { trx->get_flush_observer()) {
if (error != DB_SUCCESS) {
flush_observer->interrupted();
}
flush_observer->flush(); flush_observer->flush();
row_merge_write_redo(indexes[i]); row_merge_write_redo(indexes[i]);
} }
if (old_table != new_table
|| (indexes[i]->type & (DICT_FTS | DICT_SPATIAL))
|| error != DB_SUCCESS || !online) {
/* Do not apply any online log. */
} else {
if (global_system_variables.log_warnings > 2) { if (global_system_variables.log_warnings > 2) {
sql_print_information( sql_print_information(
"InnoDB: Online DDL : Applying" "InnoDB: Online DDL : Applying"
...@@ -5016,13 +5021,7 @@ row_merge_build_indexes( ...@@ -5016,13 +5021,7 @@ row_merge_build_indexes(
flush_observer->flush(); flush_observer->flush();
trx->remove_flush_observer(); if (old_table != new_table) {
if (trx_is_interrupted(trx)) {
error = DB_INTERRUPTED;
}
if (error == DB_SUCCESS && old_table != new_table) {
for (const dict_index_t* index for (const dict_index_t* index
= dict_table_get_first_index(new_table); = dict_table_get_first_index(new_table);
index != NULL; index != NULL;
...@@ -5033,6 +5032,12 @@ row_merge_build_indexes( ...@@ -5033,6 +5032,12 @@ row_merge_build_indexes(
} }
} }
} }
trx->remove_flush_observer();
if (trx_is_interrupted(trx)) {
error = DB_INTERRUPTED;
}
} }
DBUG_RETURN(error); DBUG_RETURN(error);
......
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