summaryrefslogtreecommitdiff
path: root/storage/innobase/trx
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-10-10 12:44:10 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-10-10 12:47:46 +0300
commitf545e3cfa9fcc6b706a6e0ee6f2af2124e514e18 (patch)
treefb1edcbeb2db72dffe67d20e36d3b381edc9ccf2 /storage/innobase/trx
parentf58a0b3afc4277f9ed077d939be135580f116352 (diff)
downloadmariadb-git-f545e3cfa9fcc6b706a6e0ee6f2af2124e514e18.tar.gz
MDEV-15562: Remove dict_table_t::rollback_instant(unsigned n)
On the rollback of changes to SYS_COLUMNS, MDEV-15562 will break the assumption that the only instantaneous changes to columns are the addition to the end of the column list. The function dict_table_t::rollback_instant(unsigned n) is inherently incompatible with instantly dropping or reordering columns. When a change to SYS_COLUMNS is rolled back, we must simply evict the affected table definition, at the end of the rollback. We cannot free the table object immediately, because the current transaction that is being rolled back may be holding a lock on the table and its metadata record. dict_table_remove_from_cache_low(): Replaced by dict_table_remove_from_cache(). dict_table_remove_from_cache(): Add a third parameter keep=false, so that the table can be freed by the caller. trx_lock_t::evicted_tables: List of tables on which trx_t::evict_table() was invoked. trx_t::evict_table(): Evict a table definition during rollback. trx_commit_in_memory(): Empty the trx->lock.evicted_tables list after the locks were released, by freeing the table objects. row_undo_ins_remove_clust_rec(), row_undo_mod_clust_low(): Invoke trx_t::evict_table() on the affected table if a change to SYS_COLUMNS is being rolled back.
Diffstat (limited to 'storage/innobase/trx')
-rw-r--r--storage/innobase/trx/trx0trx.cc43
1 files changed, 43 insertions, 0 deletions
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index d51e26aa771..600a6eb6229 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -214,6 +214,9 @@ struct TrxFactory {
lock_trx_lock_list_init(&trx->lock.trx_locks);
+ UT_LIST_INIT(trx->lock.evicted_tables,
+ &dict_table_t::table_LRU);
+
UT_LIST_INIT(
trx->trx_savepoints,
&trx_named_savept_t::trx_savepoints);
@@ -238,6 +241,7 @@ struct TrxFactory {
}
ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
UT_DELETE(trx->xid);
ut_free(trx->detailed_error);
@@ -390,6 +394,7 @@ trx_t *trx_create()
ut_ad(trx->lock.n_rec_locks == 0);
ut_ad(trx->lock.table_cached == 0);
ut_ad(trx->lock.rec_cached == 0);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
#ifdef WITH_WSREP
trx->wsrep_event = NULL;
@@ -1250,6 +1255,37 @@ trx_update_mod_tables_timestamp(
trx->mod_tables.clear();
}
+/** Evict a table definition due to the rollback of ALTER TABLE.
+@param[in] table_id table identifier */
+void trx_t::evict_table(table_id_t table_id)
+{
+ ut_ad(in_rollback);
+
+ dict_table_t* table = dict_table_open_on_id(
+ table_id, true, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
+ if (!table) {
+ return;
+ }
+
+ if (!table->release()) {
+ /* This must be a DDL operation that is being rolled
+ back in an active connection. */
+ ut_a(table->get_ref_count() == 1);
+ ut_ad(!is_recovered);
+ ut_ad(mysql_thd);
+ return;
+ }
+
+ /* This table should only be locked by this transaction, if at all. */
+ ut_ad(UT_LIST_GET_LEN(table->locks) <= 1);
+ const bool locked = UT_LIST_GET_LEN(table->locks);
+ ut_ad(!locked || UT_LIST_GET_FIRST(table->locks)->trx == this);
+ dict_table_remove_from_cache(table, true, locked);
+ if (locked) {
+ UT_LIST_ADD_FIRST(lock.evicted_tables, table);
+ }
+}
+
/****************************************************************//**
Commits a transaction in memory. */
static
@@ -1315,9 +1351,16 @@ trx_commit_in_memory(
trx_update_mod_tables_timestamp(trx);
MONITOR_INC(MONITOR_TRX_RW_COMMIT);
}
+
+ while (dict_table_t* table = UT_LIST_GET_FIRST(
+ trx->lock.evicted_tables)) {
+ UT_LIST_REMOVE(trx->lock.evicted_tables, table);
+ dict_mem_table_free(table);
+ }
}
ut_ad(!trx->rsegs.m_redo.undo);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) {
mutex_enter(&rseg->mutex);