1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
|
#
# This test tests the operation of transaction replay with a scenario
# where two subsequent write sets being applied conflict with local transaction
# in commit phase. The conflict is "false positive" confict on GAP lock in
# secondary unique index.
# The first applier will cause BF abort for the local committer, which
# starts replaying because of positive certification.
# In buggy version, the test scenario continues so that while the local transaction
# is replaying, the latter applier experiences similar UK GAP lock conflict
# and forces the replayer to abort second time.
# In fixed version, this latter replayer BF abort should not happen.
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
--source include/galera_have_debug_sync.inc
--let $expected_wsrep_local_replays = `SELECT VARIABLE_VALUE+1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 int, f3 int, unique key keyj (f2));
INSERT INTO t1 VALUES (1, 1, 0);
INSERT INTO t1 VALUES (3, 3, 0);
INSERT INTO t1 VALUES (10, 10, 0);
# we will need 2 appliers threads for applyin two writes ets in parallel in node1
# and 1 applier thread for handling replaying
SET GLOBAL wsrep_slave_threads = 3;
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
--connection node_1
# starting a transaction, which deletes and inserts the middle row in test table
# this will be victim of false positive conflict with appliers
SET SESSION wsrep_sync_wait=0;
START TRANSACTION;
DELETE FROM t1 WHERE f2 = 3;
INSERT INTO t1 VALUES (3, 3, 1);
# Control connection to manage sync points for appliers
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connection node_1a
SET SESSION wsrep_sync_wait=0;
# send from node 2 first an INSERT transaction, which will conflict on GAP lock in node 1
--connection node_2
INSERT INTO t1 VALUES (5, 5, 2);
--connection node_1a
# wait to see the INSERT in apply_cb sync point
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
# first applier seen in wait point, set sync point for the second INSERT
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_2
# send second insert into same GAP in test table
INSERT INTO t1 VALUES (4, 4, 2);
--connection node_1a
# wait for the second insert to arrive in his sync point
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
# both appliers are now waiting in separate sync points
# Block the local 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
# wait for the local commit to enter in commit monitor wait state
--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
# release the local transaction to continue with commit
--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
# and now release the first applier, it should force local trx to abort
SET GLOBAL DEBUG_DBUG = "";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
SET GLOBAL debug_dbug = NULL;
SET debug_sync='RESET';
# wait for BF abort to happen and replaying begin
--let $wait_condition = SELECT VARIABLE_VALUE= $expected_wsrep_local_replays FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
--let $wait_condition_on_error_output= SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
--source include/wait_condition_with_debug.inc
# set another sync point for second applier
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
# letting the second appier to move forward
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
# waiting until second applier is in wait state
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
# stopping second applier before commit
--let $galera_sync_point = commit_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--source include/galera_clear_sync_point.inc
# releasing the second insert, with buggy version it will conflict with
# replayer
SET GLOBAL DEBUG_DBUG = "";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
SET GLOBAL debug_dbug = NULL;
SET debug_sync='RESET';
# with fixed version, second applier has reached comit monitor, and we can
# release it to complete
--let $galera_sync_point = commit_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
# local commit should succeed
--connection node_1
--reap
SELECT * FROM t1;
# returning original slave thread count
SET GLOBAL wsrep_slave_threads = DEFAULT;
--connection node_2
SELECT * FROM t1;
# replicate some transactions, so that wsrep slave thread count can reach
# original state in node 1
INSERT INTO t1 VALUES (7,7,7);
INSERT INTO t1 VALUES (8,8,8);
SELECT COUNT(*) FROM t1;
SELECT * FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) = 7 FROM t1
--source include/wait_condition.inc
SELECT COUNT(*) FROM t1;
SELECT * FROM t1;
DROP TABLE t1;
##################################################################################
# test scenario 2
#
# commit order is now: INSERT-1, local COMMIT, INSERT-2
# while local trx is replaying, the latter applier has applied and is waiting
# for commit.
# The point in this scenario is to verify that replayer does not try to abort
# the latter applier
#################################################################################
--echo test scenario 2
--connection node_1
--let $expected_wsrep_local_replays = `SELECT VARIABLE_VALUE+1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 int, f3 int, unique key keyj (f2));
INSERT INTO t1 VALUES (1, 1, 0);
INSERT INTO t1 VALUES (3, 3, 0);
INSERT INTO t1 VALUES (10, 10, 0);
# we will need 2 appliers threads for applyin two writes sets in parallel in node1
# and 1 applier thread for handling replaying
SET GLOBAL wsrep_slave_threads = 3;
# set sync point for the first INSERT applier
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_1
# starting a transaction, which deletes and inserts the middle row in test table
# this will be victim of false positive conflict with appliers
SET SESSION wsrep_sync_wait=0;
START TRANSACTION;
DELETE FROM t1 WHERE f2 = 3;
INSERT INTO t1 VALUES (3, 3, 1);
# Control connection to manage sync points for appliers
--connection node_1a
SET SESSION wsrep_sync_wait=0;
# send from node 2 first an INSERT transaction, which will conflict on GAP lock in node 1
--connection node_2
INSERT INTO t1 VALUES (5, 5, 2);
--connection node_1a
# wait to see the INSERT in apply_cb sync point
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
# Block the local 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
# wait for the local commit to enter in commit monitor wait state
--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
# first applier is now waiting in before commit, and local trx in commit monitor
# set sync point before replaying
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_replay_cb";
# release the local transaction to continue with commit
# it should advance and end up waiting in commit monitor for his turn
--let $galera_sync_point = commit_monitor_master_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
# and now release the first applier, it should force local trx to abort
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
# wait for BF abort to happen and replaying begin
--let $wait_condition = SELECT VARIABLE_VALUE= $expected_wsrep_local_replays FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
--let $wait_condition_on_error_output= SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays';
--source include/wait_condition_with_debug.inc
# replayer should now be in stopped in sync point
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_replay_cb_reached";
# set sync point for the second INSERT
--let $galera_sync_point = commit_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_2
# send second insert into same GAP in test table
INSERT INTO t1 VALUES (4, 4, 2);
--connection node_1a
# wait for the second applier to enter in commit monitor wait state
--let $galera_sync_point = commit_monitor_slave_enter_sync
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
# and, letting the second appier to move forward, it will stop naturally
# to wait for commit order after replayer's commit
--let $galera_sync_point = commit_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--source include/galera_clear_sync_point.inc
# and now release the replayer, if all is good,it will commit before the second applier
SET GLOBAL DEBUG_DBUG = "";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_replay_cb";
SET GLOBAL debug_dbug = NULL;
SET debug_sync='RESET';
# local commit should succeed
--connection node_1
--reap
--let $wait_condition = SELECT COUNT(*)=5 FROM t1;
--source include/wait_condition.inc
# returning original slave thread count
SET GLOBAL wsrep_slave_threads = DEFAULT;
--connection node_2
SELECT * FROM t1;
# replicate some transactions, so that wsrep slave thread count can reach
# original state in node 1
INSERT INTO t1 VALUES (7,7,7);
INSERT INTO t1 VALUES (8,8,8);
SELECT COUNT(*) FROM t1;
SELECT * FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) = 7 FROM t1
--source include/wait_condition.inc
SELECT COUNT(*) FROM t1;
SELECT * FROM t1;
DROP TABLE t1;
|