From b7fe6179e82d89da55b48f6fb3061f5f4066535b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 25 Oct 2022 08:53:56 +0200 Subject: [PATCH] MDEV-29843 Do not use asynchronous log_write_upto() for system THDs Non-blocking log_write_upto (MDEV-24341) was only designed for the client connections. Fix, so it is not be triggered for any system THD. Previously, an incomplete solution only excluded Innodb purge THDs, but not the slave for example. The hang in MDEV still remains somewhat a mystery though, it is not immediately clear how exactly condition variable can become corrupted. But it is clear that it can be avoided. --- sql/sql_class.cc | 16 ++++++++++++++-- sql/sql_class.h | 3 --- storage/innobase/handler/ha_innodb.cc | 9 --------- storage/innobase/include/ha_prototypes.h | 7 ------- storage/innobase/trx/trx0trx.cc | 6 +++--- 5 files changed, 17 insertions(+), 24 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a61a7d97746..405ac8e8f31 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5127,12 +5127,22 @@ void reset_thd(MYSQL_THD thd) before writing response to client, to provide durability guarantees, in other words, server can't send OK packet before modified data is durable in redo log. -*/ -extern "C" void thd_increment_pending_ops(MYSQL_THD thd) + + NOTE: system THD (those that are not associated with client + connection) do not allows async operations yet. + + @param thd a THD + @return thd + @retval nullptr if this is system THD */ +extern "C" MYSQL_THD thd_increment_pending_ops(MYSQL_THD thd) { + if (!thd || thd->system_thread != NON_SYSTEM_THREAD) + return nullptr; thd->async_state.inc_pending_ops(); + return thd; } + /** This function can be used by plugin/engine to indicate end of async operation (such as end of group commit @@ -5143,6 +5153,8 @@ extern "C" void thd_increment_pending_ops(MYSQL_THD thd) extern "C" void thd_decrement_pending_ops(MYSQL_THD thd) { DBUG_ASSERT(thd); + DBUG_ASSERT(thd->system_thread == NON_SYSTEM_THREAD); + thd_async_state::enum_async_state state; if (thd->async_state.dec_pending_ops(&state) == 0) { diff --git a/sql/sql_class.h b/sql/sql_class.h index 6c0a4b9f5ed..e07d91edf75 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2586,9 +2586,6 @@ struct thd_async_state } }; -extern "C" void thd_increment_pending_ops(MYSQL_THD); -extern "C" void thd_decrement_pending_ops(MYSQL_THD); - /** @class THD diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7d29147d89e..9c9a9b53c3f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1823,15 +1823,6 @@ MYSQL_THD innobase_create_background_thd(const char* name) return thd; } -extern "C" void thd_increment_pending_ops(MYSQL_THD); - -THD *innodb_thd_increment_pending_ops(THD *thd) -{ - if (!thd || THDVAR(thd, background_thread)) - return nullptr; - thd_increment_pending_ops(thd); - return thd; -} /** Close opened tables, free memory, delete items for a MYSQL_THD. @param[in] thd MYSQL_THD to reset */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index d9a26226e98..da9dec05827 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -199,13 +199,6 @@ but can be used for comparison. extern "C" unsigned long long thd_start_utime(const MYSQL_THD thd); -/** - Indicate the start of an async operation in a foreground thread. -@param thd current_thd -@return thd -@retval nullptr if this is not a foreground thread */ -THD *innodb_thd_increment_pending_ops(THD *thd); - /** Determines the current SQL statement. Thread unsafe, can only be called from the thread owning the THD. @param[in] thd MySQL thread handle diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index ae92f0f80cb..f9a152e294e 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1134,8 +1134,8 @@ trx_finalize_for_fts( trx->fts_trx = NULL; } - -extern "C" void thd_decrement_pending_ops(MYSQL_THD); +extern "C" MYSQL_THD thd_increment_pending_ops(MYSQL_THD); +extern "C" void thd_decrement_pending_ops(MYSQL_THD); #include "../log/log0sync.h" @@ -1168,7 +1168,7 @@ sync: } completion_callback cb; - if ((cb.m_param = innodb_thd_increment_pending_ops(trx->mysql_thd))) + if ((cb.m_param = thd_increment_pending_ops(trx->mysql_thd))) { cb.m_callback = (void (*)(void *)) thd_decrement_pending_ops; log_write_up_to(lsn, flush, false, &cb);