Skip to content

Commit

Permalink
MDEV-24861 Assertion `trx->rsegs.m_redo.rseg' failed in innodb_prepar…
Browse files Browse the repository at this point in the history
…e_commit_versioned

trx_t::commit_tables(): Ensure that mod_tables will be empty.
This was broken in commit b08448d
where the query cache invalidation was moved from lock_release().
  • Loading branch information
dr-m committed Feb 15, 2021
1 parent 4df0249 commit 2e84846
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 26 deletions.
13 changes: 13 additions & 0 deletions mysql-test/suite/innodb/r/innodb-truncate.result
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,16 @@ ALTER TABLE t1 FORCE;
TRUNCATE TABLE t1;
ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `test`.`t3` (`f2`))
DROP TABLE t2, t1;
#
# MDEV-24861 Assertion `trx->rsegs.m_redo.rseg' failed
# in innodb_prepare_commit_versioned
#
CREATE TABLE t1 (id INT PRIMARY KEY, f TEXT UNIQUE,
s BIGINT UNSIGNED AS ROW START, e BIGINT UNSIGNED AS ROW END,
PERIOD FOR SYSTEM_TIME(s,e))
ENGINE=InnoDB WITH SYSTEM VERSIONING;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
ALTER TABLE t1 FORCE;
TRUNCATE TABLE t2;
DROP TABLE t1, t2;
# End of 10.6 tests
16 changes: 16 additions & 0 deletions mysql-test/suite/innodb/t/innodb-truncate.test
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,19 @@ ALTER TABLE t1 FORCE;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE t1;
DROP TABLE t2, t1;

--echo #
--echo # MDEV-24861 Assertion `trx->rsegs.m_redo.rseg' failed
--echo # in innodb_prepare_commit_versioned
--echo #

CREATE TABLE t1 (id INT PRIMARY KEY, f TEXT UNIQUE,
s BIGINT UNSIGNED AS ROW START, e BIGINT UNSIGNED AS ROW END,
PERIOD FOR SYSTEM_TIME(s,e))
ENGINE=InnoDB WITH SYSTEM VERSIONING;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
ALTER TABLE t1 FORCE;
TRUNCATE TABLE t2;
DROP TABLE t1, t2;

--echo # End of 10.6 tests
54 changes: 28 additions & 26 deletions storage/innobase/trx/trx0trx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1226,44 +1226,46 @@ trx_flush_log_if_needed(
/** Process tables that were modified by the committing transaction. */
inline void trx_t::commit_tables()
{
if (!undo_no || mod_tables.empty())
if (mod_tables.empty())
return;

if (undo_no)
{
#if defined SAFE_MUTEX && defined UNIV_DEBUG
const bool preserve_tables= !innodb_evict_tables_on_commit_debug ||
is_recovered || /* avoid trouble with XA recovery */
const bool preserve_tables= !innodb_evict_tables_on_commit_debug ||
is_recovered || /* avoid trouble with XA recovery */
# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
dict_sys.mutex_is_locked();
dict_sys.mutex_is_locked();
# else /* this would be more proper way to do it */
dict_operation_lock_mode || dict_operation;
dict_operation_lock_mode || dict_operation;
# endif
#endif

const trx_id_t max_trx_id= trx_sys.get_max_trx_id();
const auto now= start_time;
const trx_id_t max_trx_id= trx_sys.get_max_trx_id();
const auto now= start_time;

for (const auto& p : mod_tables)
{
dict_table_t *table= p.first;
table->update_time= now;
table->query_cache_inv_trx_id= max_trx_id;
for (const auto& p : mod_tables)
{
dict_table_t *table= p.first;
table->update_time= now;
table->query_cache_inv_trx_id= max_trx_id;

#if defined SAFE_MUTEX && defined UNIV_DEBUG
if (preserve_tables || table->get_ref_count() || table->is_temporary() ||
UT_LIST_GET_LEN(table->locks))
/* do not evict when committing DDL operations or if some other
transaction is holding the table handle */
continue;
/* recheck while holding the mutex that blocks
table->acquire() */
dict_sys.mutex_lock();
{
LockMutexGuard g{SRW_LOCK_CALL};
if (!table->get_ref_count() && !UT_LIST_GET_LEN(table->locks))
dict_sys.remove(table, true);
}
dict_sys.mutex_unlock();
if (preserve_tables || table->get_ref_count() || table->is_temporary() ||
UT_LIST_GET_LEN(table->locks))
/* do not evict when committing DDL operations or if some other
transaction is holding the table handle */
continue;
/* recheck while holding the mutex that blocks table->acquire() */
dict_sys.mutex_lock();
{
LockMutexGuard g{SRW_LOCK_CALL};
if (!table->get_ref_count() && !UT_LIST_GET_LEN(table->locks))
dict_sys.remove(table, true);
}
dict_sys.mutex_unlock();
#endif
}
}

mod_tables.clear();
Expand Down

0 comments on commit 2e84846

Please sign in to comment.