diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-10 15:42:50 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-10 15:42:50 +0200 |
commit | ea37b144094a0c2ebfc6774047fd473c1b2a8658 (patch) | |
tree | ac43eaa1550923945bd16d0d6d4b2aa1cf062c2f /storage/innobase/fts/fts0opt.cc | |
parent | e47bd0073cc082a4a7668ace1d272fa3bea538ab (diff) | |
download | mariadb-git-ea37b144094a0c2ebfc6774047fd473c1b2a8658.tar.gz |
MDEV-16678 Prefer MDL to dict_sys.latch for innodb background tasks
This is joint work with Thirunarayanan Balathandayuthapani.
The MDL interface between InnoDB and the rest of the server
(in storage/innobase/dict/dict0dict.cc and in include/)
is my work, while most everything else is Thiru's.
The collection of InnoDB persistent statistics and the
defragmentation were not refactored to use MDL. They will
keep relying on lower-level interlocking with
fil_check_pending_operations().
The purge of transaction history and the background operations on
fulltext indexes will use MDL. We will revert
commit 2c4844c9e76427525e8c39a2d72686085efe89c3
(MDEV-17813) because thanks to MDL, purge cannot conflict
with DDL operations anymore. For a similar reason, we will remove
the MDEV-16222 test case from gcol.innodb_virtual_debug_purge.
Purge is essentially replacing all use of the global dict_sys.latch
with MDL. Purge will skip the undo log records for tables whose names
start with #sql-ib or #sql2. Theoretically, such tables might
be renamed back to visible table names if TRUNCATE fails to
create a new table, or the final rename in ALTER TABLE...ALGORITHM=COPY
fails. In that case, purge could permanently leave some garbage
in the table. Such garbage will be tolerated; the table would not
be considered corrupted.
To avoid repeated MDL releases and acquisitions,
trx_purge_attach_undo_recs() will sort undo log records by table_id,
and purge_node_t will keep the MDL and table handle open for multiple
successive undo log records.
get_purge_table(): A new accessor, used during the purge of
history for indexed virtual columns. This interface should ideally
not exist at all.
thd_mdl_context(): Accessor of THD::mdl_context.
Wrapped in a new thd_mdl_service.
dict_get_db_name_len(): Define inline.
dict_acquire_mdl_shared(): Acquire explicit shared MDL on a table name
if needed.
dict_table_open_on_id(): Return MDL_ticket, if requested.
dict_table_close(): Release MDL ticket, if requested.
dict_fts_index_syncing(), dict_index_t::index_fts_syncing: Remove.
row_drop_table_for_mysql() no longer needs to check these, because
MDL guarantees that a fulltext index sync will not be in progress
while MDL_EXCLUSIVE is protecting a DDL operation.
dict_table_t::parse_name(): Parse the table name for acquiring MDL.
purge_node_t::undo_recs: Change the type to std::list<trx_purge_rec_t*>
(different container, and storing also roll_ptr).
purge_node_t: Add mdl_ticket, last_table_id, purge_thd, mdl_hold_recs
for acquiring MDL and for keeping the table open across multiple
undo log records.
purge_vcol_info_t, row_purge_store_vsec_cur(), row_purge_restore_vsec_cur():
Remove. We will acquire the MDL earlier.
purge_sys_t::heap: Added, for reading undo log records.
fts_sync_during_ddl(): Invoked during ALGORITHM=INPLACE operations
to ensure that fts_sync_table() will not conflict with MDL_EXCLUSIVE.
Uses fts_t::sync_message for bookkeeping.
Diffstat (limited to 'storage/innobase/fts/fts0opt.cc')
-rw-r--r-- | storage/innobase/fts/fts0opt.cc | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 2d13a4b32e4..ab4ba8f852e 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -45,6 +45,8 @@ static tpool::timer* timer; static tpool::task_group task_group(1); static tpool::task task(fts_optimize_callback,0, &task_group); +/** FTS optimize thread, for MDL acquisition */ +static THD *fts_opt_thd; /** The FTS vector to store fts_slot_t */ static ib_vector_t* fts_slots; @@ -2564,12 +2566,6 @@ void fts_optimize_add_table(dict_table_t* table) return; } - /* If there is no fts index present then don't add to - optimize queue. */ - if (!ib_vector_size(table->fts->indexes)) { - return; - } - /* Make sure table with FTS index cannot be evicted */ dict_table_prevent_eviction(table); @@ -2627,6 +2623,8 @@ fts_optimize_remove_table( remove->event = event; msg->ptr = remove; + ut_ad(!mutex_own(&dict_sys.mutex)); + add_msg(msg, true); mutex_exit(&fts_optimize_wq->mutex); @@ -2664,7 +2662,7 @@ fts_optimize_request_sync_table( add_msg(msg, true); - table->fts->in_queue = true; + table->fts->in_queue = table->fts->sync_message = true; mutex_exit(&fts_optimize_wq->mutex); } @@ -2791,14 +2789,34 @@ static bool fts_is_sync_needed() } /** Sync fts cache of a table -@param[in,out] table table to be synced */ -static void fts_optimize_sync_table(dict_table_t* table) +@param[in,out] table table to be synced +@param[in] process_message processing messages from fts_optimize_wq */ +static void fts_optimize_sync_table(dict_table_t *table, + bool process_message= false) { - if (table->fts && table->fts->cache && fil_table_accessible(table)) { - fts_sync_table(table, false); - } - - DBUG_EXECUTE_IF("ib_optimize_wq_hang", os_thread_sleep(6000000);); + MDL_ticket* mdl_ticket= nullptr; + dict_table_t *sync_table= dict_acquire_mdl_shared<true>(table, fts_opt_thd, + &mdl_ticket); + + if (!sync_table) + return; + + if (sync_table->fts && sync_table->fts->cache && + fil_table_accessible(sync_table)) + { + fts_sync_table(sync_table, false); + if (process_message) + { + mutex_enter(&fts_optimize_wq->mutex); + sync_table->fts->sync_message = false; + mutex_exit(&fts_optimize_wq->mutex); + } + } + + DBUG_EXECUTE_IF("ib_optimize_wq_hang", os_thread_sleep(6000000);); + + if (mdl_ticket) + dict_table_close(sync_table, false, false, fts_opt_thd, mdl_ticket); } /**********************************************************************//** @@ -2806,11 +2824,6 @@ Optimize all FTS tables. @return Dummy return */ static void fts_optimize_callback(void *) { - static ulint current = 0; - static ibool done = FALSE; - static ulint n_tables = ib_vector_size(fts_slots); - static ulint n_optimize = 0; - ut_ad(!srv_read_only_mode); if (!fts_optimize_wq) { @@ -2818,6 +2831,11 @@ static void fts_optimize_callback(void *) return; } + static ulint current = 0; + static ibool done = FALSE; + static ulint n_tables = ib_vector_size(fts_slots); + static ulint n_optimize = 0; + while (!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) { /* If there is no message in the queue and we have tables @@ -2889,7 +2907,8 @@ static void fts_optimize_callback(void *) os_thread_sleep(300000);); fts_optimize_sync_table( - static_cast<dict_table_t*>(msg->ptr)); + static_cast<dict_table_t*>(msg->ptr), + true); break; default: @@ -2917,6 +2936,7 @@ static void fts_optimize_callback(void *) ib_vector_free(fts_slots); fts_slots = NULL; + innobase_destroy_background_thd(fts_opt_thd); ib::info() << "FTS optimize thread exiting."; os_event_set(fts_opt_shutdown_event); @@ -2946,6 +2966,7 @@ fts_optimize_init(void) heap_alloc = ib_heap_allocator_create(heap); fts_slots = ib_vector_create(heap_alloc, sizeof(fts_slot_t), 4); + fts_opt_thd = innobase_create_background_thd("InnoDB FTS optimizer"); /* Add fts tables to fts_slots which could be skipped during dict_load_table_one() because fts_optimize_thread wasn't even started. */ @@ -3004,4 +3025,24 @@ fts_optimize_shutdown() os_event_destroy(fts_opt_shutdown_event); ib_wqueue_free(fts_optimize_wq); fts_optimize_wq = NULL; + fts_opt_thd = NULL; +} + +/** Sync the table during commit phase +@param[in] table table to be synced */ +void fts_sync_during_ddl(dict_table_t* table) +{ + mutex_enter(&fts_optimize_wq->mutex); + if (!table->fts->sync_message) + { + mutex_exit(&fts_optimize_wq->mutex); + return; + } + + mutex_exit(&fts_optimize_wq->mutex); + fts_sync_table(table, false); + + mutex_enter(&fts_optimize_wq->mutex); + table->fts->sync_message = false; + mutex_exit(&fts_optimize_wq->mutex); } |