Skip to content

Commit

Permalink
MDEV-32787 : Assertion `!wsrep_has_changes(thd) || (thd->lex->sql_com…
Browse files Browse the repository at this point in the history
…mand == SQLCOM_CREATE_TABLE && !thd->is_current_stmt_binlog_format_row()) || thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted' failed in void wsrep_commit_empty(THD*, bool)

When we commit empty transaction we should allow wsrep
transaction to be on s_must_replay state for DDL that
was killed during certification.

Fix is tested with RQG because deterministic mtr-testcase
was not found.

Signed-off-by: Julius Goryavsky <julius.goryavsky@mariadb.com>
  • Loading branch information
janlindstrom authored and sysprg committed Mar 25, 2024
1 parent 70b9077 commit e9d3344
Showing 1 changed file with 37 additions and 21 deletions.
58 changes: 37 additions & 21 deletions sql/wsrep_mysqld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3468,36 +3468,52 @@ void wsrep_ready_set(bool ready_value)
step is performed to leave the wsrep transaction in the state as it
never existed.
This should not be an inline functions as it requires a lot of stack space
because of WSREP_DBUG() usage. It's also not a function that is
frequently called.
*/

void wsrep_commit_empty(THD* thd, bool all)
{
DBUG_ENTER("wsrep_commit_empty");
WSREP_DEBUG("wsrep_commit_empty for %llu client_state %s client_mode"
" %s trans_state %s sql %s",
thd_get_thread_id(thd),
wsrep::to_c_string(thd->wsrep_cs().state()),
wsrep::to_c_string(thd->wsrep_cs().mode()),
wsrep::to_c_string(thd->wsrep_cs().transaction().state()),
wsrep_thd_query(thd));

if (wsrep_is_real(thd, all) &&
wsrep_thd_is_local(thd) &&
thd->wsrep_trx().active() &&
!thd->internal_transaction() &&
thd->wsrep_trx().state() != wsrep::transaction::s_committed)
{
/* Here transaction is either empty (i.e. no changes) or
it was CREATE TABLE with no row binlog format or
we have already aborted transaction e.g. because max writeset size
has been reached. */
DBUG_ASSERT(!wsrep_has_changes(thd) ||
(thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
!thd->is_current_stmt_binlog_format_row()) ||
thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted);
#ifndef DBUG_OFF
const bool empty= !wsrep_has_changes(thd);
const bool create= thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
!thd->is_current_stmt_binlog_format_row();
const bool aborted= thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted;
const bool ddl_replay= ((sql_command_flags[thd->lex->sql_command] &
(CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) &&
thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay);
/* Here transaction is either
(1) empty (i.e. no changes) or
(2) it was CREATE TABLE with no row binlog format or
(3) we have already aborted transaction e.g. because max writeset size
has been reached or
(4) it was DDL and got BF aborted and must replay.
*/
if(!(empty || create || aborted || ddl_replay))
{
WSREP_DEBUG("wsrep_commit_empty: thread: %llu client_state: %s client_mode:"
" %s trans_state: %s error: %s empty: %d create: %d aborted:"
" %d ddl_replay: %d sql: %s",
thd_get_thread_id(thd),
wsrep::to_c_string(thd->wsrep_cs().state()),
wsrep::to_c_string(thd->wsrep_cs().mode()),
wsrep::to_c_string(thd->wsrep_cs().transaction().state()),
wsrep::to_c_string(thd->wsrep_cs().current_error()),
empty, create, aborted, ddl_replay,
wsrep_thd_query(thd));

DBUG_ASSERT(empty || // 1
create || // 2
aborted || // 3
ddl_replay); // 4
}
#endif /* DBUG_OFF */
bool have_error= wsrep_current_error(thd);
int ret= wsrep_before_rollback(thd, all) ||
wsrep_after_rollback(thd, all) ||
Expand All @@ -3511,10 +3527,10 @@ void wsrep_commit_empty(THD* thd, bool all)
DBUG_ASSERT(wsrep_current_error(thd) == wsrep::e_deadlock_error);
thd->wsrep_cs().reset_error();
}

if (ret)
{
WSREP_DEBUG("wsrep_commit_empty failed: %d", wsrep_current_error(thd));
}
WSREP_DEBUG("wsrep_commit_empty failed: %s",
wsrep::to_c_string(thd->wsrep_cs().current_error()));
}
DBUG_VOID_RETURN;
}

0 comments on commit e9d3344

Please sign in to comment.