From 56a79743b84219f81a5f7ad0987b85b8184aa347 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Thu, 14 Jul 2022 17:13:27 +0200 Subject: [PATCH] Implement logic to be able to get a consistent GTID This adds logic so that with a `START TRANSACTION WITH CONSISTENT SNAPSHOT`, we can also get a correct GTID that is appropriate at the time the transaction is started. It locks around the logic when a consistent snapshot is created in the underlying storage engine and grabs the current GTID under lock at that point. That means that no other threads can update the GTID at the exact same point in time avoiding the race that currently exists if you execute `SELECT @@global.gtid_executed` which doesn't enforce such locking. The locking overhead is should be relatively small. When using a consistent read snapshots, systems (like Vitess) often want to get a consistent GTID. Today that's only possible by then also locking all tables which is much more expensive. Signed-off-by: Dirkjan Bussink --- sql/handler.cc | 10 ++++++++++ sql/rpl_context.cc | 11 +++++++++++ sql/rpl_context.h | 11 +++++++++++ sql/sys_vars.cc | 2 +- sql/system_variables.h | 3 ++- 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 5520a4ebaa43..fd2355470e90 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2326,8 +2326,18 @@ static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg) { int ha_start_consistent_snapshot(THD *thd) { bool warn = true; + /* + Grabbing the write lock here since we end up calling + store_start_gtid => notify_start_gtid_determined => ensure_sidno + which wants the write lock to potentially expand storage for sidnos. + */ + global_sid_lock->wrlock(); + thd->rpl_thd_ctx.session_gtids_ctx().notify_start_gtid_determined(thd); + plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn); + global_sid_lock->unlock(); + /* Same idea as when one wants to CREATE TABLE in one engine which does not exist: diff --git a/sql/rpl_context.cc b/sql/rpl_context.cc index 5f23c2c1846c..31ce154046c2 100644 --- a/sql/rpl_context.cc +++ b/sql/rpl_context.cc @@ -133,6 +133,17 @@ bool Session_consistency_gtids_ctx::notify_after_gtid_executed_update( return res; } +void Session_consistency_gtids_ctx::notify_start_gtid_determined(const THD *thd) { + DBUG_TRACE; + assert(thd); + + if (m_listener == nullptr || m_curr_session_track_gtids != SESSION_TRACK_GTIDS_START_GTID) return; + + if (m_gtid_set->add_gtid_set(gtid_state->get_executed_gtids()) == RETURN_STATUS_OK) { + notify_ctx_change_listener(); + } +} + void Session_consistency_gtids_ctx:: update_tracking_activeness_from_session_variable(const THD *thd) { m_curr_session_track_gtids = thd->variables.session_track_gtids; diff --git a/sql/rpl_context.h b/sql/rpl_context.h index cfcfff436af3..97175217b648 100644 --- a/sql/rpl_context.h +++ b/sql/rpl_context.h @@ -206,6 +206,17 @@ class Session_consistency_gtids_ctx { */ void update_tracking_activeness_from_session_variable(const THD *thd); + /** + This function SHALL be called once the starting GTID for the given transaction has + has been determined. + + This function SHALL store the data if the + thd->variables.session_track_gtids is set to START_GTID. + + @param thd The thread context. + */ + virtual void notify_start_gtid_determined(const THD *thd); + private: // not implemented Session_consistency_gtids_ctx(const Session_consistency_gtids_ctx &rsc); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index a56e467635a7..a2ee8a5e1752 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1514,7 +1514,7 @@ static bool on_session_track_gtids_update(sys_var *, THD *thd, enum_var_type) { } static const char *session_track_gtids_names[] = {"OFF", "OWN_GTID", - "ALL_GTIDS", NullS}; + "ALL_GTIDS", "START_GTID", NullS}; static Sys_var_enum Sys_session_track_gtids( "session_track_gtids", "Controls the amount of global transaction ids to be " diff --git a/sql/system_variables.h b/sql/system_variables.h index 8bf8b2cdc3de..52389dc75409 100644 --- a/sql/system_variables.h +++ b/sql/system_variables.h @@ -90,7 +90,8 @@ enum enum_transaction_write_set_hashing_algorithm { enum enum_session_track_gtids { SESSION_TRACK_GTIDS_OFF = 0, SESSION_TRACK_GTIDS_OWN_GTID = 1, - SESSION_TRACK_GTIDS_ALL_GTIDS = 2 + SESSION_TRACK_GTIDS_ALL_GTIDS = 2, + SESSION_TRACK_GTIDS_START_GTID = 3 }; /** Values for use_secondary_engine sysvar. */