mirror of
https://github.com/MariaDB/server.git
synced 2025-11-30 05:23:50 +03:00
When a transaction fails in certification phase, it has connsumed one GTID, but as transaction must rollback, it will not go for commit ordering, and because of this also the wsrep XID checkpointing can happen out of order. This PR will make the thread, which has failed for certiication failure to wait for its commit order turn for checkpointing wsrep IXD in innodb rollback segment. There is a specific test for wsrep XID checkpointing ordering in mtr test: mysql-wsrep-bugs-607, which is added in this PR. Test galera_slave_replay depends also on this fix, as the second test phase may also assert for bad wsrep XID checkpointing order. galera_slave_replay.test had also other problems, which caused the test to fail immediately, thse are now fixes in this PR as well.
198 lines
5.7 KiB
Plaintext
198 lines
5.7 KiB
Plaintext
#
|
|
# This test tests the operation of transaction replay for async replication slave.
|
|
# If a potentially conflicting galera transaction arrives at
|
|
# just the right time during the commit and has lock conflict with async replication transaction
|
|
# applied by slave SQL thread, then the async replication transaction should either abort
|
|
# or rollback and replay (depending on the nature of lock conflict).
|
|
#
|
|
|
|
--source include/have_innodb.inc
|
|
--source include/have_log_bin.inc
|
|
--source include/have_debug.inc
|
|
--source include/have_debug_sync.inc
|
|
--source include/galera_have_debug_sync.inc
|
|
|
|
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
|
|
|
--connection node_2a
|
|
--source include/galera_cluster.inc
|
|
|
|
#
|
|
# node 3 is native MariaDB server operating as async replication master
|
|
#
|
|
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
|
|
--connection node_3
|
|
RESET MASTER;
|
|
|
|
--connection node_2a
|
|
#
|
|
# count the number of wsrep replay's done in the node
|
|
#
|
|
--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
|
|
|
|
|
#
|
|
# nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB master in node 3
|
|
#
|
|
--disable_query_log
|
|
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3;
|
|
--enable_query_log
|
|
START SLAVE;
|
|
|
|
--connection node_3
|
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) engine=innodb;
|
|
INSERT INTO t1 VALUES (1, 'a');
|
|
INSERT INTO t1 VALUES (3, 'a');
|
|
|
|
#
|
|
# use statement format replication to cause a false positive conflict with async replication transaction
|
|
# and galera replication. The conflict will be on GAP lock, and slave SQL thread should rollback
|
|
# and replay
|
|
#
|
|
set binlog_format=STATEMENT;
|
|
|
|
SET AUTOCOMMIT=ON;
|
|
START TRANSACTION;
|
|
|
|
SELECT * FROM t1 FOR UPDATE;
|
|
UPDATE t1 SET f2 = 'c' WHERE f1 > 1;
|
|
|
|
--connection node_2a
|
|
# wait for create table and inserts to be replicated from master
|
|
SET SESSION wsrep_sync_wait = 0;
|
|
--let $wait_condition = SELECT COUNT(*) = 2 FROM test.t1;
|
|
--source include/wait_condition.inc
|
|
|
|
# wait for create table and inserts to be replicated in cluster
|
|
--connection node_1
|
|
SET SESSION wsrep_sync_wait = 0;
|
|
--let $wait_condition = SELECT COUNT(*) = 2 FROM test.t1;
|
|
--source include/wait_condition.inc
|
|
|
|
--connection node_2a
|
|
# Block the future commit of async replication
|
|
--let $galera_sync_point = commit_monitor_master_enter_sync
|
|
--source include/galera_set_sync_point.inc
|
|
|
|
# block also the applier before applying begins
|
|
SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb";
|
|
|
|
#
|
|
# now inject a conflicting insert from node 1, it will replicate with
|
|
# earlier seqno (than async transaction) and pause before applying in node 2
|
|
#
|
|
--connection node_1
|
|
INSERT INTO test.t1 VALUES (2, 'b');
|
|
|
|
#
|
|
# send the update from master, this will succeed here, beceuase of async replication.
|
|
# async replication will apply this in node 2 and pause before commit phase,
|
|
--connection node_3
|
|
--error 0
|
|
COMMIT;
|
|
|
|
# Wait until async slave commit is blocked in node_2
|
|
--connection node_2a
|
|
--source include/galera_wait_sync_point.inc
|
|
|
|
#
|
|
# release the applier
|
|
# note: have to clear wsrep_apply_cb sync point first, as async replication will go for replay
|
|
# and as this sync point, after BF applier is released to progress
|
|
#
|
|
SET GLOBAL debug_dbug = "";
|
|
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
|
|
|
# Unblock the async slave commit
|
|
--connection node_2a
|
|
--source include/galera_clear_sync_point.inc
|
|
--source include/galera_signal_sync_point.inc
|
|
|
|
--connection node_3
|
|
|
|
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a';
|
|
SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
|
|
SELECT * FROM t1;
|
|
|
|
--connection node_2a
|
|
|
|
# wsrep_local_replays has increased by 1
|
|
set session wsrep_sync_wait=15;
|
|
--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
|
set session wsrep_sync_wait=0;
|
|
|
|
--disable_query_log
|
|
--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
|
|
--enable_query_log
|
|
|
|
#
|
|
# replaying of async transaction should be effective, and row 3 having 'c' in f2
|
|
#
|
|
SELECT * FROM t1;
|
|
SET DEBUG_SYNC = "RESET";
|
|
|
|
#********************************************************************************
|
|
# test phase 2
|
|
#********************************************************************************
|
|
|
|
--echo #
|
|
--echo # test phase with real abort
|
|
--echo #
|
|
|
|
--connection node_3
|
|
|
|
set binlog_format=ROW;
|
|
|
|
insert into t1 values (4, 'd');
|
|
|
|
SET AUTOCOMMIT=ON;
|
|
START TRANSACTION;
|
|
|
|
UPDATE t1 SET f2 = 'd' WHERE f1 = 3;
|
|
|
|
--connection node_2a
|
|
# wait for the last insert to be replicated from master
|
|
--let $wait_condition = SELECT COUNT(*) = 4 FROM test.t1;
|
|
--source include/wait_condition.inc
|
|
|
|
# block applier
|
|
SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb";
|
|
|
|
# Inject a conflicting update from node 1
|
|
--connection node_1
|
|
UPDATE test.t1 SET f2 = 'e' WHERE f1 = 3;
|
|
|
|
--connection node_2a
|
|
# wait until applier has reached the sync point
|
|
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
|
|
--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
|
|
|
|
# send the update from master
|
|
--connection node_3
|
|
--error 0
|
|
COMMIT;
|
|
|
|
--connection node_2a
|
|
--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
|
|
--source include/wait_condition.inc
|
|
|
|
# release the applier from node 1
|
|
SET GLOBAL debug_dbug = "";
|
|
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
|
|
|
--connection node_2a
|
|
|
|
set session wsrep_sync_wait=15;
|
|
SELECT COUNT(*) = 1 FROM test.t1 WHERE f2 = 'e';
|
|
set session wsrep_sync_wait=0;
|
|
|
|
STOP SLAVE;
|
|
RESET SLAVE;
|
|
SET DEBUG_SYNC = "RESET";
|
|
|
|
DROP TABLE t1;
|
|
|
|
--connection node_3
|
|
DROP TABLE t1;
|
|
RESET MASTER;
|