From 25737dbab7fec6d05a50353baf5b15ad97dcbd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 13 Mar 2025 11:48:03 +0200 Subject: [PATCH] MDEV-33850 : For Galera, create sequence with low cache got signal 6 error: [ERROR] WSREP: FSM: no such a transition REPLICATING -> COMMITTED Problem was that transacton was BF-aborted after certification succeeded and transaction tried to rollback and during rollback binlog stmt cache containing sequence value reservations was written into binlog. Transaction must replay because certification succeeded but transaction must not be written into binlog yet, it will be done during commit after the replay. Fix is to skip binlog write if transaction must replay and in replay we need to reset binlog stmt cache. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 1 - .../suite/galera/r/galera_sequences.result | 3 + .../galera/r/galera_sequences_bf_kill.result | 152 ++++++++ .../r/galera_sequences_transaction.result | 350 ++++++++++++++++++ .../suite/galera/t/galera_sequences.test | 2 + .../galera/t/galera_sequences_bf_kill.cnf | 9 + .../t/galera_sequences_bf_kill.combinations | 5 + .../galera/t/galera_sequences_bf_kill.test | 115 ++++++ .../galera/t/galera_sequences_transaction.cnf | 9 + .../galera_sequences_transaction.combinations | 5 + .../t/galera_sequences_transaction.test | 255 +++++++++++++ sql/log.cc | 10 + sql/wsrep_client_service.cc | 6 + 13 files changed, 921 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_sequences_bf_kill.result create mode 100644 mysql-test/suite/galera/r/galera_sequences_transaction.result create mode 100644 mysql-test/suite/galera/t/galera_sequences_bf_kill.cnf create mode 100644 mysql-test/suite/galera/t/galera_sequences_bf_kill.combinations create mode 100644 mysql-test/suite/galera/t/galera_sequences_bf_kill.test create mode 100644 mysql-test/suite/galera/t/galera_sequences_transaction.cnf create mode 100644 mysql-test/suite/galera/t/galera_sequences_transaction.combinations create mode 100644 mysql-test/suite/galera/t/galera_sequences_transaction.test diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 538d2d36759..23bf40c409a 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -10,7 +10,6 @@ # ############################################################################## -galera_sequences : MDEV-35934/MDEV-33850 For Galera, create sequence with low cache got signal 6 error: [ERROR] WSREP: FSM: no such a transition REPLICATING -> COMMITTED galera_wan : MDEV-35940 Unallowed state transition: donor -> synced in galera_wan galera_vote_rejoin_ddl : MDEV-35940 Unallowed state transition: donor -> synced in galera_wan MW-329 : MDEV-35951 Complete freeze during MW-329 test diff --git a/mysql-test/suite/galera/r/galera_sequences.result b/mysql-test/suite/galera/r/galera_sequences.result index e78b89d4b09..7cdeffff1e3 100644 --- a/mysql-test/suite/galera/r/galera_sequences.result +++ b/mysql-test/suite/galera/r/galera_sequences.result @@ -47,6 +47,9 @@ select NEXT VALUE FOR Seq1_1; NEXT VALUE FOR Seq1_1 4 connection node_1; +SHOW CREATE SEQUENCE Seq1_1; +Table Create Table +Seq1_1 CREATE SEQUENCE `Seq1_1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB DROP SEQUENCE Seq1_1; connection node_1; CREATE TABLE t2 (d CHAR(1)KEY); diff --git a/mysql-test/suite/galera/r/galera_sequences_bf_kill.result b/mysql-test/suite/galera/r/galera_sequences_bf_kill.result new file mode 100644 index 00000000000..39d11337b4f --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sequences_bf_kill.result @@ -0,0 +1,152 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE SEQUENCE s INCREMENT=0 CACHE=5 ENGINE=InnoDB; +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (3, 0); +connection node_1; +START TRANSACTION; +INSERT INTO t1 VALUES (4, next value for s); +INSERT INTO t1 VALUES (5, next value for s); +INSERT INTO t1 VALUES (6, next value for s); +INSERT INTO t1 VALUES (7, next value for s); +INSERT INTO t1 VALUES (8, next value for s); +INSERT INTO t1 VALUES (9, next value for s); +INSERT INTO t1 VALUES (10, next value for s); +INSERT INTO t1 VALUES (11, next value for s); +INSERT INTO t1 VALUES (12, next value for s); +INSERT INTO t1 VALUES (13, next value for s); +INSERT INTO t1 VALUES (14, next value for s); +SELECT * FROM t1 WHERE f1 > 0 FOR UPDATE; +f1 f2 +1 0 +3 0 +4 1 +5 3 +6 5 +7 7 +8 9 +9 11 +10 13 +11 15 +12 17 +13 19 +14 21 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +INSERT INTO t1 VALUES (2, 2); +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +connection node_1; +COMMIT; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +connection node_1; +wsrep_local_replays +1 +INSERT INTO t1 VALUES (22, next value for s); +INSERT INTO t1 VALUES (23, next value for s); +INSERT INTO t1 VALUES (24, next value for s); +INSERT INTO t1 VALUES (25, next value for s); +INSERT INTO t1 VALUES (26, next value for s); +INSERT INTO t1 VALUES (27, next value for s); +INSERT INTO t1 VALUES (28, next value for s); +INSERT INTO t1 VALUES (29, next value for s); +INSERT INTO t1 VALUES (30, next value for s); +INSERT INTO t1 VALUES (31, next value for s); +INSERT INTO t1 VALUES (32, next value for s); +INSERT INTO t1 VALUES (33, next value for s); +INSERT INTO t1 VALUES (34, next value for s); +INSERT INTO t1 VALUES (35, next value for s); +connection node_1; +SELECT * FROM t1; +f1 f2 +1 0 +2 2 +3 0 +4 1 +5 3 +6 5 +7 7 +8 9 +9 11 +10 13 +11 15 +12 17 +13 19 +14 21 +22 31 +23 33 +24 35 +25 37 +26 39 +27 41 +28 43 +29 45 +30 47 +31 49 +32 51 +33 53 +34 55 +35 57 +SELECT LASTVAL(s); +LASTVAL(s) +57 +connection node_2; +SELECT * FROM t1; +f1 f2 +1 0 +2 2 +3 0 +4 1 +5 3 +6 5 +7 7 +8 9 +9 11 +10 13 +11 15 +12 17 +13 19 +14 21 +22 31 +23 33 +24 35 +25 37 +26 39 +27 41 +28 43 +29 45 +30 47 +31 49 +32 51 +33 53 +34 55 +35 57 +SELECT LASTVAL(s); +LASTVAL(s) +NULL +connection node_1; +SELECT NEXTVAL(s); +NEXTVAL(s) +59 +connection node_2; +SELECT NEXTVAL(s); +NEXTVAL(s) +62 +DROP SEQUENCE s; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_sequences_transaction.result b/mysql-test/suite/galera/r/galera_sequences_transaction.result new file mode 100644 index 00000000000..c1cfdc4aa20 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sequences_transaction.result @@ -0,0 +1,350 @@ +connection node_2; +connection node_1; +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; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +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); +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; +connection node_2; +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); +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; +connection node_2a; +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); +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; +connection node_1a; +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); +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; +connection node_2; +SELECT LASTVAL(s); +LASTVAL(s) +40 +connection node_1; +SELECT LASTVAL(s); +LASTVAL(s) +19 +connection node_2a; +SELECT LASTVAL(s); +LASTVAL(s) +60 +connection node_1a; +SELECT LASTVAL(s); +LASTVAL(s) +79 +connection node_1; +SELECT * FROM t1; +f1 f2 +1 1 +3 1 +5 1 +7 1 +9 1 +11 1 +13 1 +15 1 +17 1 +19 1 +22 1 +24 1 +26 1 +28 1 +30 1 +32 1 +34 1 +36 1 +38 1 +40 1 +42 1 +44 1 +46 1 +48 1 +50 1 +52 1 +54 1 +56 1 +58 1 +60 1 +61 1 +63 1 +65 1 +67 1 +69 1 +71 1 +73 1 +75 1 +77 1 +79 1 +connection node_2; +SELECT * FROM t1; +f1 f2 +1 1 +3 1 +5 1 +7 1 +9 1 +11 1 +13 1 +15 1 +17 1 +19 1 +22 1 +24 1 +26 1 +28 1 +30 1 +32 1 +34 1 +36 1 +38 1 +40 1 +42 1 +44 1 +46 1 +48 1 +50 1 +52 1 +54 1 +56 1 +58 1 +60 1 +61 1 +63 1 +65 1 +67 1 +69 1 +71 1 +73 1 +75 1 +77 1 +79 1 +connection node_1; +DROP TABLE t1; +DROP SEQUENCE s; +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); +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); +ROLLBACK; +connection node_2; +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); +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); +ROLLBACK; +connection node_2a; +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); +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); +ROLLBACK; +connection node_1a; +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); +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); +ROLLBACK; +connection node_2; +SELECT LASTVAL(s); +LASTVAL(s) +20 +connection node_1; +SELECT LASTVAL(s); +LASTVAL(s) +19 +connection node_2a; +SELECT LASTVAL(s); +LASTVAL(s) +40 +connection node_1a; +SELECT LASTVAL(s); +LASTVAL(s) +39 +connection node_1; +SELECT * FROM t1; +f1 f2 +connection node_2; +SELECT * FROM t1; +f1 f2 +connection node_1; +DROP TABLE t1; +DROP SEQUENCE s; +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); +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_1a; +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); +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_2a; +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); +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_2; +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); +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; +COMMIT; +connection node_1a; +ROLLBACK; +connection node_2; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2a; +ROLLBACK; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; +SELECT LASTVAL(s); +LASTVAL(s) +40 +connection node_1; +SELECT LASTVAL(s); +LASTVAL(s) +19 +connection node_2a; +SELECT LASTVAL(s); +LASTVAL(s) +20 +connection node_1a; +SELECT LASTVAL(s); +LASTVAL(s) +39 +connection node_1; +SELECT * FROM t1; +f1 f2 +1 1 +3 1 +5 1 +7 1 +9 1 +11 1 +13 1 +15 1 +17 1 +19 1 +connection node_2; +SELECT * FROM t1; +f1 f2 +1 1 +3 1 +5 1 +7 1 +9 1 +11 1 +13 1 +15 1 +17 1 +19 1 +connection node_1; +DROP TABLE t1; +DROP SEQUENCE s; diff --git a/mysql-test/suite/galera/t/galera_sequences.test b/mysql-test/suite/galera/t/galera_sequences.test index db388de2551..9e18353893b 100644 --- a/mysql-test/suite/galera/t/galera_sequences.test +++ b/mysql-test/suite/galera/t/galera_sequences.test @@ -3,6 +3,7 @@ --source include/have_sequence.inc --source include/have_aria.inc +--disable_ps2_protocol # # MDEV-19353 : Alter Sequence do not replicate to another nodes with in Galera Cluster # @@ -47,6 +48,7 @@ SHOW CREATE SEQUENCE Seq1_1; select NEXT VALUE FOR Seq1_1; --connection node_1 +SHOW CREATE SEQUENCE Seq1_1; DROP SEQUENCE Seq1_1; # diff --git a/mysql-test/suite/galera/t/galera_sequences_bf_kill.cnf b/mysql-test/suite/galera/t/galera_sequences_bf_kill.cnf new file mode 100644 index 00000000000..8701e86db5f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_bf_kill.cnf @@ -0,0 +1,9 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +auto-increment-increment=2 +auto-increment-offset=1 + +[mysqld.2] +auto-increment-increment=2 +auto-increment-offset=2 diff --git a/mysql-test/suite/galera/t/galera_sequences_bf_kill.combinations b/mysql-test/suite/galera/t/galera_sequences_bf_kill.combinations new file mode 100644 index 00000000000..cef98e75213 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_bf_kill.combinations @@ -0,0 +1,5 @@ +[binlogon] +log-bin +log-slave-updates + +[binlogoff] diff --git a/mysql-test/suite/galera/t/galera_sequences_bf_kill.test b/mysql-test/suite/galera/t/galera_sequences_bf_kill.test new file mode 100644 index 00000000000..3c53a103d44 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_bf_kill.test @@ -0,0 +1,115 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + +--disable_ps2_protocol +# +# We create InnoDB seqeuence with small cache that is then +# used as default value for column in table. +# +--connection node_1 +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +CREATE SEQUENCE s INCREMENT=0 CACHE=5 ENGINE=InnoDB; +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (3, 0); +--connection node_1 +START TRANSACTION; +INSERT INTO t1 VALUES (4, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (5, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (6, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (7, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (8, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (9, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (10, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (11, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (12, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (13, next value for s); # No conflict in cert +INSERT INTO t1 VALUES (14, next value for s); # No conflict in cert +SELECT * FROM t1 WHERE f1 > 0 FOR UPDATE; # Should cause GAP lock between 1 and 3 + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait=0; +# Block the applier on node #1 and issue a conflicting update on node #2 +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +# +# Send conflicting INSERT +# +--connection node_2 +INSERT INTO t1 VALUES (2, 2); # This should BF abort because of GAP lock + +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +# Block the commit, send the COMMIT and wait until it gets blocked +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_1 +--send COMMIT + +--connection node_1a + +--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# Let the transactions proceed +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_signal_sync_point.inc + +# Commit succeeds +--connection node_1 +--reap + +# wsrep_local_replays has increased by 1 +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays; +--enable_query_log + +INSERT INTO t1 VALUES (22, next value for s); +INSERT INTO t1 VALUES (23, next value for s); +INSERT INTO t1 VALUES (24, next value for s); +INSERT INTO t1 VALUES (25, next value for s); +INSERT INTO t1 VALUES (26, next value for s); +INSERT INTO t1 VALUES (27, next value for s); +INSERT INTO t1 VALUES (28, next value for s); +INSERT INTO t1 VALUES (29, next value for s); +INSERT INTO t1 VALUES (30, next value for s); +INSERT INTO t1 VALUES (31, next value for s); +INSERT INTO t1 VALUES (32, next value for s); +INSERT INTO t1 VALUES (33, next value for s); +INSERT INTO t1 VALUES (34, next value for s); +INSERT INTO t1 VALUES (35, next value for s); + +--connection node_1 +SELECT * FROM t1; +SELECT LASTVAL(s); + +--connection node_2 +SELECT * FROM t1; +SELECT LASTVAL(s); + +--connection node_1 +SELECT NEXTVAL(s); + +--connection node_2 +SELECT NEXTVAL(s); + +DROP SEQUENCE s; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_sequences_transaction.cnf b/mysql-test/suite/galera/t/galera_sequences_transaction.cnf new file mode 100644 index 00000000000..8701e86db5f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_transaction.cnf @@ -0,0 +1,9 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +auto-increment-increment=2 +auto-increment-offset=1 + +[mysqld.2] +auto-increment-increment=2 +auto-increment-offset=2 diff --git a/mysql-test/suite/galera/t/galera_sequences_transaction.combinations b/mysql-test/suite/galera/t/galera_sequences_transaction.combinations new file mode 100644 index 00000000000..cef98e75213 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_transaction.combinations @@ -0,0 +1,5 @@ +[binlogon] +log-bin +log-slave-updates + +[binlogoff] diff --git a/mysql-test/suite/galera/t/galera_sequences_transaction.test b/mysql-test/suite/galera/t/galera_sequences_transaction.test new file mode 100644 index 00000000000..f3dc7d51285 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequences_transaction.test @@ -0,0 +1,255 @@ +--source include/galera_cluster.inc +--source include/have_sequence.inc + +--disable_ps2_protocol +# +# Case 1: Separate transactions from few connections +# +--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; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--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); +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; + +--connection node_2 +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); +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; + +--connection node_2a +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); +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; + +--connection node_1a +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); +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; + +--connection node_2 +SELECT LASTVAL(s); +--connection node_1 +SELECT LASTVAL(s); +--connection node_2a +SELECT LASTVAL(s); +--connection node_1a +SELECT LASTVAL(s); + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; +DROP SEQUENCE s; + +# +# Case 2: All rollback +# +--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); +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); +ROLLBACK; + +--connection node_2 +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); +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); +ROLLBACK; + +--connection node_2a +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); +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); +ROLLBACK; + +--connection node_1a +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); +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); +ROLLBACK; + +--connection node_2 +SELECT LASTVAL(s); +--connection node_1 +SELECT LASTVAL(s); +--connection node_2a +SELECT LASTVAL(s); +--connection node_1a +SELECT LASTVAL(s); + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; +DROP SEQUENCE s; +# +# Case 3: Mixed transactions +# +--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); +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_1a +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); +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_2a +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); +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_2 +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); +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 +COMMIT; +--connection node_1a +ROLLBACK; +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; +--connection node_2a +--error ER_LOCK_DEADLOCK +ROLLBACK; + +--connection node_2 +SELECT LASTVAL(s); +--connection node_1 +SELECT LASTVAL(s); +--connection node_2a +SELECT LASTVAL(s); +--connection node_1a +SELECT LASTVAL(s); + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; +DROP SEQUENCE s; diff --git a/sql/log.cc b/sql/log.cc index 0131acbb83d..1ad927ef9e5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1812,6 +1812,16 @@ binlog_flush_cache(THD *thd, binlog_cache_mngr *cache_mngr, if (using_trx && thd->binlog_flush_pending_rows_event(TRUE, TRUE)) DBUG_RETURN(1); +#ifdef WITH_WSREP + /* Wsrep transaction was BF aborted but it must replay because certification + succeeded. The transaction must not be written into binlog yet, it will + be done during commit after the replay. */ + if (WSREP(thd) && wsrep_must_replay(thd)) + { + DBUG_RETURN(0); + } +#endif /* WITH_WSREP */ + /* Doing a commit or a rollback including non-transactional tables, i.e., ending a transaction where we might write the transaction diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc index 808c92f0516..cde58defd03 100644 --- a/sql/wsrep_client_service.cc +++ b/sql/wsrep_client_service.cc @@ -306,6 +306,12 @@ enum wsrep::provider::status Wsrep_client_service::replay() replayer_service.replay_status(ret); } + // In Galera we allow only InnoDB sequences, thus + // sequence table updates are in writeset. + // Binlog cache needs reset so that binlog_close + // does not write cache to binlog file yet. + binlog_reset_cache(m_thd); + replayer_thd->main_security_ctx = old_ctx; delete replayer_thd; DBUG_RETURN(ret);