diff --git a/mysql-test/suite/innodb/r/log_inplace_alter_with_exclusiv_lock.result b/mysql-test/suite/innodb/r/log_inplace_alter_with_exclusiv_lock.result new file mode 100644 index 00000000000..78fe03124e8 --- /dev/null +++ b/mysql-test/suite/innodb/r/log_inplace_alter_with_exclusiv_lock.result @@ -0,0 +1,14 @@ +# +#Bug#106163 Inplace Add index with lock=exclusive doesn't generate MLOG_ADD_INDEX redo +# +SET GLOBAL innodb_checkpoint_disabled=1; +CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB TABLESPACE=innodb_file_per_table; +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 ADD INDEX(a), ALGORITHM=INPLACE, LOCK=EXCLUSIVE; +# Kill and restart:--debug=d,ib_log +Pattern "scan .*:.*log rec MLOG_INDEX_LOAD" found +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +# restart +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/log_inplace_alter_with_exclusiv_lock.test b/mysql-test/suite/innodb/t/log_inplace_alter_with_exclusiv_lock.test new file mode 100644 index 00000000000..eba54217257 --- /dev/null +++ b/mysql-test/suite/innodb/t/log_inplace_alter_with_exclusiv_lock.test @@ -0,0 +1,28 @@ +--source include/have_debug.inc + +--echo # +--echo #Bug#106163 Inplace Add index with lock=exclusive doesn't generate MLOG_ADD_INDEX redo +--echo # + +SET GLOBAL innodb_checkpoint_disabled=1; +CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB TABLESPACE=innodb_file_per_table; +# MLOG_INDEX_LOAD will not be emitted for empty tables. Insert a row. +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 ADD INDEX(a), ALGORITHM=INPLACE, LOCK=EXCLUSIVE; + +--let $restart_parameters = restart:--debug="d,ib_log" +--source include/kill_and_restart_mysqld.inc + +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; +# Look for MLOG_INDEX_LOAD in the error log. +let SEARCH_PATTERN=scan .*:.*log rec MLOG_INDEX_LOAD; +--source include/search_pattern.inc + +CHECK TABLE t1; + +# Remove the --debug=d,ib_log setting. +--let $restart_parameters = +--source include/restart_mysqld.inc + +DROP TABLE t1; + diff --git a/storage/innobase/ddl/ddl0builder.cc b/storage/innobase/ddl/ddl0builder.cc index b844a2492a7..76ab5143a10 100644 --- a/storage/innobase/ddl/ddl0builder.cc +++ b/storage/innobase/ddl/ddl0builder.cc @@ -1897,7 +1897,7 @@ dberr_t Builder::fts_sort_and_build() noexcept { } } -dberr_t Builder::finalize() noexcept { +dberr_t Builder::finalize(bool apply_log) noexcept { ut_a(m_ctx.m_need_observer); ut_a(get_state() == State::FINISH); @@ -1919,11 +1919,13 @@ dberr_t Builder::finalize() noexcept { if (err == DB_SUCCESS) { write_redo(m_index); - DEBUG_SYNC_C_IF_THD(m_ctx.thd(), "row_log_apply_before"); + if (apply_log) { + DEBUG_SYNC_C_IF_THD(m_ctx.thd(), "row_log_apply_before"); - err = row_log_apply(m_ctx.m_trx, m_index, m_ctx.m_table, m_local_stage); + err = row_log_apply(m_ctx.m_trx, m_index, m_ctx.m_table, m_local_stage); - DEBUG_SYNC_C_IF_THD(m_ctx.thd(), "row_log_apply_after"); + DEBUG_SYNC_C_IF_THD(m_ctx.thd(), "row_log_apply_after"); + } } if (err != DB_SUCCESS) { @@ -2001,17 +2003,17 @@ dberr_t Builder::finish() noexcept { dberr_t err{DB_SUCCESS}; - if (get_error() != DB_SUCCESS || !m_ctx.m_online) { + if (get_error() == DB_SUCCESS && !m_index->table->is_temporary()) { + bool apply_log = true; /* Do not apply any online log. */ - } else if (m_ctx.m_old_table != m_ctx.m_new_table) { - ut_a(!m_index->online_log); - ut_a(m_index->online_status == ONLINE_INDEX_COMPLETE); - - auto observer = m_ctx.m_trx->flush_observer; - observer->flush(); - - } else { - err = finalize(); + if (!m_ctx.m_online) { + apply_log = false; + } else if (m_ctx.m_old_table != m_ctx.m_new_table) { + ut_a(!m_index->online_log); + ut_a(m_index->online_status == ONLINE_INDEX_COMPLETE); + apply_log = false; + } + err = finalize(apply_log); if (err != DB_SUCCESS) { set_error(err); diff --git a/storage/innobase/include/ddl0impl-builder.h b/storage/innobase/include/ddl0impl-builder.h index 7a026012c65..816853b08d3 100644 --- a/storage/innobase/include/ddl0impl-builder.h +++ b/storage/innobase/include/ddl0impl-builder.h @@ -266,8 +266,9 @@ struct Builder { [[nodiscard]] dberr_t create_merge_sort_tasks() noexcept; /** Flush all dirty pages, apply the row log and write the redo log record. + @param[in] apply_log apply the row log @return DB_SUCCESS or error code. */ - dberr_t finalize() noexcept; + dberr_t finalize(bool apply_log) noexcept; /** Convert the field data from compact to redundant format. @param[in] trx Current transaction