Commit 97582f1c authored by sjaakola's avatar sjaakola Committed by Jan Lindström

MDEV-27649 PS conflict handling causing node crash

Handling BF abort for prepared statement execution so that EXECUTE processing will continue
until parameter setup is complete, before BF abort bails out the statement execution.

THD class has new boolean member: wsrep_delayed_BF_abort, which is set if BF abort is observed
in do_command() right after reading client's packet, and if the client has sent PS execute command.
In such case, the deadlock error is not returned immediately back to client, but the PS execution
will be started. However, the PS execution loop, will now check if wsrep_delayed_BF_abort is set, and
stop the PS execution after the type information has been assigned for the PS.
With this, the PS protocol type information, which is present in the first PS EXECUTE command, is not lost
even if the first PS EXECUTE command was marked to abort.
Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
parent 8e9e1c39
...@@ -666,6 +666,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) ...@@ -666,6 +666,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
wsrep_replicate_GTID(false), wsrep_replicate_GTID(false),
wsrep_ignore_table(false), wsrep_ignore_table(false),
wsrep_aborter(0), wsrep_aborter(0),
wsrep_delayed_BF_abort(false),
/* wsrep-lib */ /* wsrep-lib */
m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID), m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID),
......
...@@ -4897,6 +4897,10 @@ class THD: public THD_count, /* this must be first */ ...@@ -4897,6 +4897,10 @@ class THD: public THD_count, /* this must be first */
/* thread who has started kill for this THD protected by LOCK_thd_data*/ /* thread who has started kill for this THD protected by LOCK_thd_data*/
my_thread_id wsrep_aborter; my_thread_id wsrep_aborter;
/* true if BF abort is observed in do_command() right after reading
client's packet, and if the client has sent PS execute command. */
bool wsrep_delayed_BF_abort;
/* /*
Transaction id: Transaction id:
* m_wsrep_next_trx_id is assigned on the first query after * m_wsrep_next_trx_id is assigned on the first query after
......
...@@ -1313,7 +1313,13 @@ bool do_command(THD *thd) ...@@ -1313,7 +1313,13 @@ bool do_command(THD *thd)
DBUG_ASSERT(!thd->mdl_context.has_locks()); DBUG_ASSERT(!thd->mdl_context.has_locks());
DBUG_ASSERT(!thd->get_stmt_da()->is_set()); DBUG_ASSERT(!thd->get_stmt_da()->is_set());
/* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */ /* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */
if (command != COM_STMT_CLOSE && if (command == COM_STMT_EXECUTE)
{
WSREP_DEBUG("PS BF aborted at do_command");
thd->wsrep_delayed_BF_abort= true;
}
if (command != COM_STMT_CLOSE &&
command != COM_STMT_EXECUTE &&
command != COM_QUIT) command != COM_QUIT)
{ {
my_error(ER_LOCK_DEADLOCK, MYF(0)); my_error(ER_LOCK_DEADLOCK, MYF(0));
...@@ -1385,6 +1391,17 @@ bool do_command(THD *thd) ...@@ -1385,6 +1391,17 @@ bool do_command(THD *thd)
/* there was a command to process, and before_command() has been called */ /* there was a command to process, and before_command() has been called */
wsrep_after_command_after_result(thd); wsrep_after_command_after_result(thd);
} }
if (thd->wsrep_delayed_BF_abort)
{
my_error(ER_LOCK_DEADLOCK, MYF(0));
WSREP_DEBUG("Deadlock error for PS query: %s", thd->query());
thd->reset_killed();
thd->mysys_var->abort = 0;
thd->wsrep_retry_counter = 0;
thd->wsrep_delayed_BF_abort= false;
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
DBUG_RETURN(return_value); DBUG_RETURN(return_value);
} }
......
...@@ -4461,7 +4461,13 @@ Prepared_statement::execute_loop(String *expanded_query, ...@@ -4461,7 +4461,13 @@ Prepared_statement::execute_loop(String *expanded_query,
if (set_parameters(expanded_query, packet, packet_end)) if (set_parameters(expanded_query, packet, packet_end))
return TRUE; return TRUE;
#ifdef WITH_WSREP
if (thd->wsrep_delayed_BF_abort)
{
WSREP_DEBUG("delayed BF abort, quitting execute_loop, stmt: %d", id);
return TRUE;
}
#endif /* WITH_WSREP */
reexecute: reexecute:
// Make sure that reprepare() did not create any new Items. // Make sure that reprepare() did not create any new Items.
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment