mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
This commit fixes a sporadic failure with the test case 1, where recorded result depends on node 1 applying node 2's replicated sequence update before it resumes its already-open transaction: - Node 2 SELECT NEXTVAL(s) writes reserved_until=21 and replicates it. - On node 1 that lands in Rows_log_event::update_sequence() Since 21 > next_free_value (9), adjust_values(21) discards node 1's still-cached value 9. Nothing enforced that ordering: node 1's INSERTs run inside BEGIN, and sync wait does not happen mid-transaction. The fix is to use selarate session, node_1_ctrl, to wait until node 1 has applied the update, before node 1 resumes its transaction
237 lines
7.6 KiB
Plaintext
237 lines
7.6 KiB
Plaintext
#
|
|
# Test sequences crash recovery.
|
|
#
|
|
|
|
--source include/galera_cluster.inc
|
|
--source include/have_sequence.inc
|
|
--source include/big_test.inc
|
|
--source include/no_protocol.inc
|
|
|
|
--disable_ps2_protocol
|
|
|
|
#
|
|
# Case 1: Crash a node during a transaction, bring the
|
|
# sequence in sync by receiving higher current value
|
|
#
|
|
--connection node_1
|
|
CREATE SEQUENCE s INCREMENT=0 CACHE=5 ENGINE=InnoDB;
|
|
CREATE TABLE t1 (f1 INT PRIMARY KEY DEFAULT NEXTVAL(s), f2 INT) ENGINE=InnoDB;
|
|
|
|
--connection node_1
|
|
BEGIN;
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
|
|
--connect node_1_ctrl, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
|
--connection node_1_ctrl
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_2
|
|
BEGIN;
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
|
|
--echo # Crash and restart the node, losing the transaction (1)
|
|
--source include/kill_galera.inc
|
|
--let $galera_wsrep_recover_server_id=2
|
|
--source include/galera_wsrep_recover.inc
|
|
--let $start_mysqld_params =
|
|
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
|
--source include/start_mysqld.inc
|
|
|
|
--connection node_1
|
|
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
--connection node_2
|
|
--echo # Wait for the next_not_cached_value = 11 FROM s (1)
|
|
--let $wait_condition = SELECT next_not_cached_value = 11 FROM s;
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
# Check and update the last written sequence value
|
|
SELECT NEXTVAL(s);
|
|
SELECT LASTVAL(s);
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
# Node 1 has an open transaction and wsrep_sync_wait is not effective
|
|
# inside a transaction. Wait here until node 1 has applied the sequence
|
|
# update replicated by NEXTVAL above, otherwise node 1 may still consume
|
|
# its own cached value before the update arrives.
|
|
--connection node_1_ctrl
|
|
--echo # Wait for the next_not_cached_value = 21 FROM s (1_ctrl)
|
|
--let $wait_condition = SELECT next_not_cached_value = 21 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
--connection node_1
|
|
# Update the sequence value further
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
COMMIT;
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
SELECT LASTVAL(s);
|
|
SELECT COUNT(*) FROM t1;
|
|
SELECT * FROM t1;
|
|
|
|
--connection node_2
|
|
--let $wait_condition = SELECT COUNT(*) = 10 FROM t1
|
|
--source include/wait_condition.inc
|
|
--echo # Wait for the next_not_cached_value = 42 FROM s
|
|
--let $wait_condition = SELECT next_not_cached_value = 42 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
# The next value should be in sync now, but the last
|
|
# value is still the same
|
|
SELECT LASTVAL(s);
|
|
SELECT NEXTVAL(s);
|
|
SELECT * FROM t1;
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_1
|
|
DROP TABLE t1;
|
|
DROP SEQUENCE s;
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
#
|
|
# Case 2: Crash a node during a transaction, bring the
|
|
# sequence in sync by sending higher current value
|
|
#
|
|
--connection node_1
|
|
CREATE SEQUENCE s INCREMENT=0 CACHE=5 ENGINE=InnoDB;
|
|
CREATE TABLE t1 (f1 INT PRIMARY KEY DEFAULT NEXTVAL(s), f2 INT) ENGINE=InnoDB;
|
|
|
|
--connection node_1
|
|
BEGIN;
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
|
|
--connection node_1_ctrl
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_2
|
|
# Exhaust the cached values once, but no replication happens even
|
|
# though the sequnce table is updated
|
|
BEGIN;
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
INSERT INTO t1(f2) values (2);
|
|
|
|
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
SET SESSION wsrep_sync_wait=0;
|
|
--echo # Wait for the next_not_cached_value = 31 FROM s (2a)
|
|
--let $wait_condition = SELECT next_not_cached_value = 31 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
SELECT next_not_cached_value = 31 FROM s;
|
|
|
|
--connection node_2
|
|
--echo # Crash and restart the node, losing the transaction (2)
|
|
--source include/kill_galera.inc
|
|
--let $galera_wsrep_recover_server_id=2
|
|
--source include/galera_wsrep_recover.inc
|
|
--let $start_mysqld_params =
|
|
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
|
--source include/start_mysqld.inc
|
|
|
|
--connection node_1
|
|
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
|
--source include/wait_condition.inc
|
|
|
|
--connection node_2
|
|
--echo # Wait for the next_not_cached_value = 31 FROM s (2)
|
|
--let $wait_condition = SELECT next_not_cached_value = 31 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
SELECT LASTVAL(s);
|
|
|
|
--connection node_1
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
INSERT INTO t1(f2) values (1);
|
|
SELECT COUNT(*) FROM t1;
|
|
|
|
COMMIT;
|
|
SELECT LASTVAL(s);
|
|
SELECT * FROM t1;
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_2
|
|
--let $wait_condition = SELECT COUNT(*) = 15 FROM t1
|
|
--source include/wait_condition.inc
|
|
--echo # Wait for the next_not_cached_value = 31 FROM s
|
|
--let $wait_condition = SELECT next_not_cached_value = 31 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
|
|
# Check and update the last written sequence value, it's still
|
|
# higher than the one from the other node
|
|
SELECT LASTVAL(s);
|
|
SELECT NEXTVAL(s);
|
|
SELECT * FROM t1;
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_1
|
|
--let $wait_condition = SELECT COUNT(*) = 15 FROM t1
|
|
--source include/wait_condition.inc
|
|
--let $wait_condition = SELECT LASTVAL(s) = 29
|
|
--let $wait_condition_on_error_output = SELECT LASTVAL(s)
|
|
--source include/wait_condition_with_debug.inc
|
|
--echo # Wait for the next_not_cached_value = 41 FROM s
|
|
--let $wait_condition = SELECT next_not_cached_value = 41 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
# The next value should be in sync now, but the last
|
|
# value is still the same
|
|
SELECT LASTVAL(s);
|
|
SELECT NEXTVAL(s);
|
|
SET GLOBAL innodb_log_checkpoint_now=1;
|
|
|
|
--connection node_2
|
|
--let $wait_condition = SELECT LASTVAL(s) = 32
|
|
--let $wait_condition_on_error_output = SELECT LASTVAL(s)
|
|
--source include/wait_condition_with_debug.inc
|
|
--echo # Wait for the next_not_cached_value = 52 FROM s
|
|
--let $wait_condition = SELECT next_not_cached_value = 52 FROM s
|
|
--let $wait_condition_on_error_output = SELECT next_not_cached_value FROM s
|
|
--source include/wait_condition_with_debug.inc
|
|
SELECT LASTVAL(s);
|
|
SELECT * from t1;
|
|
|
|
--connection node_1
|
|
SELECT * FROM t1;
|
|
DROP TABLE t1;
|
|
DROP SEQUENCE s;
|