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

MDEV-31285 : Assertion `state() == s_executing || state() == s_preparing ||

state() == s_prepared || state() == s_must_abort || state() == s_aborting ||
state() == s_cert_failed || state() == s_must_replay' failed

When applier tries to execute write rows event it find out
in table_def::compatible_with that value is not compatible
and sets error and thd->is_slave_error but thd->is_error()
is false. Later in rpl_group_info::slave_close_thread_tables
we commit stmt. This is bad for Galera because later in
apply_write_set we notice that event apply was not successful
and try to rollback transaction, but wsrep transaction
is already in s_committed state.

This is fixed on rpl_group_info::slave_close_thread_tables
so that in Galera case we rollback stmt if thd->is_slave_error
or thd->is_error() is set. Then later we can rollback wsrep
transaction.
Signed-off-by: default avatarJulius Goryavsky <julius.goryavsky@mariadb.com>
parent c1bc0560
connection node_2;
connection node_1;
connection node_1;
connection node_2;
connection node_1;
CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i;
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`i` int(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING
SELECT * from t;
i
1
DROP TABLE IF EXISTS t;
COMMIT;
connection node_2;
SET SESSION wsrep_sync_wait=0;
Killing server ...
Starting server ...
connection node_2;
call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*");
call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*");
--source include/galera_cluster.inc
--let $node_1 = node_1
--let $node_2 = node_2
--source include/auto_increment_offset_save.inc
--connection node_1
CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i;
SHOW CREATE TABLE t;
SELECT * from t;
DROP TABLE IF EXISTS t;
COMMIT;
#
# Restart node_2, force SST because database is inconsistent compared to node_1
#
--connection node_2
SET SESSION wsrep_sync_wait=0;
--source include/kill_galera.inc
--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
--echo Starting server ...
let $restart_noprint=2;
--source include/start_mysqld.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc
--connection node_2
call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*");
call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*");
--source include/auto_increment_offset_restore.inc
......@@ -2377,7 +2377,17 @@ void rpl_group_info::slave_close_thread_tables(THD *thd)
{
DBUG_ENTER("rpl_group_info::slave_close_thread_tables(THD *thd)");
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
#ifdef WITH_WSREP
// This can happen e.g. when table_def::compatible_with fails and sets a error
// but thd->is_error() is false then. However, we do not want to commit
// statement on Galera instead we want to rollback it as later in
// apply_write_set we rollback transaction and that can't be done
// after wsrep transaction state is s_committed.
if (WSREP(thd))
(thd->is_error() || thd->is_slave_error) ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
else
#endif
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->get_stmt_da()->set_overwrite_status(false);
close_thread_tables(thd);
......
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