Commit e9d33443 authored by Jan Lindström's avatar Jan Lindström Committed by Julius Goryavsky

MDEV-32787 : Assertion `!wsrep_has_changes(thd) || (thd->lex->sql_command ==...

MDEV-32787 : Assertion `!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' 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: default avatarJulius Goryavsky <julius.goryavsky@mariadb.com>
parent 70b90772
......@@ -3468,21 +3468,11 @@ 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) &&
......@@ -3490,14 +3480,40 @@ void wsrep_commit_empty(THD* thd, bool all)
!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) ||
......@@ -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;
}
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