summaryrefslogtreecommitdiff
path: root/storage/innobase/fts/fts0opt.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-12-10 15:42:50 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-12-10 15:42:50 +0200
commitea37b144094a0c2ebfc6774047fd473c1b2a8658 (patch)
treeac43eaa1550923945bd16d0d6d4b2aa1cf062c2f /storage/innobase/fts/fts0opt.cc
parente47bd0073cc082a4a7668ace1d272fa3bea538ab (diff)
downloadmariadb-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.cc81
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);
}