mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 17:33:44 +01:00
Merge 10.1 into 10.2
This commit is contained in:
commit
5f55f69e4a
12 changed files with 1056 additions and 11 deletions
20
mysql-test/suite/galera/r/MDEV-20225.result
Normal file
20
mysql-test/suite/galera/r/MDEV-20225.result
Normal file
|
@ -0,0 +1,20 @@
|
|||
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
|
||||
CREATE TABLE t2 (f1 INT NOT NULL PRIMARY KEY AUTO_INCREMENT, f2 INT) ENGINE=InnoDB;
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (NULL, NEW.f1);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL debug_dbug = 'd,sync.mdev_20225';
|
||||
DROP TRIGGER tr1;
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
connection node_2;
|
||||
SET GLOBAL debug_dbug = 'RESET';
|
||||
SET DEBUG_SYNC = 'now SIGNAL signal.mdev_20225_continue';
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
SET GLOBAL wsrep_slave_threads = 1;
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
360
mysql-test/suite/galera/r/galera_sp_bf_abort.result
Normal file
360
mysql-test/suite/galera/r/galera_sp_bf_abort.result
Normal file
|
@ -0,0 +1,360 @@
|
|||
connection node_1;
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
|
||||
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert()
|
||||
BEGIN
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert_with_exit_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert_with_continue_handler()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert_with_continue_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert_transaction()
|
||||
BEGIN
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert_transaction;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Warnings:
|
||||
Error 1317 Query execution was interrupted
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert_transaction_with_continue_handler()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert_transaction_with_continue_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Warnings:
|
||||
Error 1317 Query execution was interrupted
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_update_insert_transaction_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_update_insert_transaction_with_exit_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Warnings:
|
||||
Error 1317 Query execution was interrupted
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 b
|
||||
2 c
|
||||
3 b
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict()
|
||||
BEGIN
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_insert_insert_conflict;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Got one of the listed errors
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 a
|
||||
2 c
|
||||
3 a
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT "Conflict exit handler";
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_insert_insert_conflict_with_exit_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Conflict exit handler
|
||||
Conflict exit handler
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 a
|
||||
2 c
|
||||
3 a
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
connection node_1;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict_with_continue_handler()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT "Conflict continue handler";
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1a;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_2;
|
||||
INSERT INTO t1 VALUES (2, 'c');
|
||||
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,after_replicate_sync';
|
||||
connection node_1;
|
||||
CALL proc_insert_insert_conflict_with_continue_handler;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync';
|
||||
connection node_1;
|
||||
Conflict continue handler
|
||||
Conflict continue handler
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 a
|
||||
2 c
|
||||
3 a
|
||||
4 d
|
||||
wsrep_local_replays
|
||||
1
|
||||
DELETE FROM t1;
|
||||
DROP PROCEDURE proc_update_insert;
|
||||
DROP PROCEDURE proc_update_insert_with_continue_handler;
|
||||
DROP PROCEDURE proc_update_insert_with_exit_handler;
|
||||
DROP PROCEDURE proc_update_insert_transaction;
|
||||
DROP PROCEDURE proc_update_insert_transaction_with_continue_handler;
|
||||
DROP PROCEDURE proc_update_insert_transaction_with_exit_handler;
|
||||
DROP PROCEDURE proc_insert_insert_conflict;
|
||||
DROP PROCEDURE proc_insert_insert_conflict_with_exit_handler;
|
||||
DROP PROCEDURE proc_insert_insert_conflict_with_continue_handler;
|
||||
DROP TABLE t1;
|
52
mysql-test/suite/galera/t/MDEV-20225.test
Normal file
52
mysql-test/suite/galera/t/MDEV-20225.test
Normal file
|
@ -0,0 +1,52 @@
|
|||
#
|
||||
# MDEV-20225 - Verify that DROP TRIGGER gets keys assigned corresponding
|
||||
# to all affected tables.
|
||||
#
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source suite/galera/include/galera_have_debug_sync.inc
|
||||
|
||||
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
|
||||
CREATE TABLE t2 (f1 INT NOT NULL PRIMARY KEY AUTO_INCREMENT, f2 INT) ENGINE=InnoDB;
|
||||
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (NULL, NEW.f1);
|
||||
|
||||
--connection node_2
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL debug_dbug = 'd,sync.mdev_20225';
|
||||
|
||||
--let $galera_connection_name = node_1a
|
||||
--let $galera_server_number = 1
|
||||
--source include/galera_connect.inc
|
||||
DROP TRIGGER tr1;
|
||||
|
||||
--connection node_2
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
|
||||
--connection node_1
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
# We must rely on sleep here. If the bug is fixed, the second applier
|
||||
# is not allowed to go past apply monitor which would trigger the bug,
|
||||
# so there is no sync point or condition to wait.
|
||||
--sleep 1
|
||||
|
||||
--connection node_2
|
||||
SET GLOBAL debug_dbug = 'RESET';
|
||||
SET DEBUG_SYNC = 'now SIGNAL signal.mdev_20225_continue';
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
SET GLOBAL wsrep_slave_threads = 1;
|
||||
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t1;
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# Trigger should now be dropped on node_2.
|
||||
SHOW TRIGGERS;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
36
mysql-test/suite/galera/t/galera_sp_bf_abort.inc
Normal file
36
mysql-test/suite/galera/t/galera_sp_bf_abort.inc
Normal file
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Issue an INSERT for gap between 1 and 3 to node_2 and wait until it hits
|
||||
# apply monitor sync point on node_1
|
||||
#
|
||||
|
||||
--connection node_1a
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_set_sync_point.inc
|
||||
|
||||
--connection node_2
|
||||
--eval $galera_sp_bf_abort_conflict
|
||||
|
||||
--connection node_1a
|
||||
--source include/galera_wait_sync_point.inc
|
||||
--source include/galera_clear_sync_point.inc
|
||||
|
||||
# Send a procedure to node_1 which should take a gap lock between
|
||||
# rows 1 and 3. It does not conflict with INSERT from node_2 in
|
||||
# certification. Park the UPDATE after replicate and let INSERT to
|
||||
# continue applying, generating a BF abort.
|
||||
|
||||
--let $galera_sync_point = after_replicate_sync
|
||||
--source include/galera_set_sync_point.inc
|
||||
|
||||
--connection node_1
|
||||
--send_eval CALL $galera_sp_bf_abort_proc
|
||||
|
||||
--connection node_1a
|
||||
--let $galera_sync_point = after_replicate_sync apply_monitor_slave_enter_sync
|
||||
--source include/galera_wait_sync_point.inc
|
||||
--source include/galera_clear_sync_point.inc
|
||||
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_signal_sync_point.inc
|
||||
--let $galera_sync_point = after_replicate_sync
|
||||
--source include/galera_signal_sync_point.inc
|
350
mysql-test/suite/galera/t/galera_sp_bf_abort.test
Normal file
350
mysql-test/suite/galera/t/galera_sp_bf_abort.test
Normal file
|
@ -0,0 +1,350 @@
|
|||
#
|
||||
# Test cases for stored procedure BF aborts.
|
||||
#
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source suite/galera/include/galera_have_debug_sync.inc
|
||||
|
||||
--connection node_1
|
||||
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
|
||||
|
||||
# Control connection for Galera sync point management
|
||||
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||
--connection node_1a
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 1a: Procedure does and UPDATE which will suffer BF abort
|
||||
# but there is no actual conflict and non-conflicting INSERT.
|
||||
# The expected outcome is that both UPDATE and INSERT will succedd
|
||||
# and no errors are reported to the client, wsrep_local_replays is
|
||||
# incremented by one.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert()
|
||||
BEGIN
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 1b: Procedure does and UPDATE which will suffer BF abort
|
||||
# but there is no actual conflict and non-conflicting INSERT.
|
||||
# An EXIT HANDLER is declared for the procedure.
|
||||
# The expected outcome is that both UPDATE and INSERT will succedd
|
||||
# and no errors are reported to the client, wsrep_local_replays is
|
||||
# incremented by one.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert_with_exit_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 1c: Procedure does and UPDATE which will suffer BF abort
|
||||
# but there is no actual conflict and non-conflicting INSERT.
|
||||
# A CONTINUE HANDLER is declared for the procedure.
|
||||
# The expected outcome is that both UPDATE and INSERT will succedd
|
||||
# and no errors are reported to the client, wsrep_local_replays is
|
||||
# incremented by one.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert_with_continue_handler()
|
||||
BEGIN
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert_with_continue_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 2a: UPDATE and INSERT are run inside a transaction and the transaction
|
||||
# will be BF aborted on COMMIT. The expected outcome is that the transaction
|
||||
# succeeds and no errors are reported to the client, wsrep_local_replays
|
||||
# is incremented by one.
|
||||
#
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert_transaction()
|
||||
BEGIN
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert_transaction
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 2b: UPDATE and INSERT are run inside a transaction and the transaction
|
||||
# will be BF aborted on COMMIT. A CONTINUE HANDLER is declared for the
|
||||
# procedure. The expected outcome is that the transaction
|
||||
# succeeds and no errors are reported to the client, wsrep_local_replays
|
||||
# is incremented by one.
|
||||
#
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert_transaction_with_continue_handler()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert_transaction_with_continue_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Case 2c: UPDATE and INSERT are run inside a transaction and the transaction
|
||||
# will be BF aborted on COMMIT. An EXIT HANDLE is declared for the procedure.
|
||||
# The expected outcome is that the transaction succeeds and no errors are
|
||||
# reported to the client, wsrep_local_replays is incremented by one.
|
||||
#
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_update_insert_transaction_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
|
||||
START TRANSACTION;
|
||||
UPDATE t1 SET f2 = 'b';
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
COMMIT;
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_update_insert_transaction_with_exit_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 1 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
|
||||
#
|
||||
# Case 3a: Two INSERTs are run inside stored procedure, this time
|
||||
# the first INSERT will have a BF abort and real conflict. The expected outcome
|
||||
# is that the INSERT fails and an error is reported to the client.
|
||||
# wsrep_local_replays is not incremented.
|
||||
#
|
||||
# Notice that the resulting error code may be both
|
||||
# ER_DUP_ENTRY (procedure will exit with cert failure conflict state and
|
||||
# will be) or ER_LOCK_DEADLOCK depending on timing.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict()
|
||||
BEGIN
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_insert_insert_conflict
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--error ER_DUP_ENTRY,ER_LOCK_DEADLOCK, ER_ERROR_DURING_COMMIT
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 0 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
|
||||
#
|
||||
# Case 3b: Two INSERTs are run inside stored procedure, this time
|
||||
# the first INSERT will have a BF abort and real conflict.
|
||||
# An EXIT HANDLER is declared for the procedure. The expected outcome
|
||||
# is that the INSERT fails and an error is reported to the client.
|
||||
# wsrep_local_replays is not incremented.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict_with_exit_handler()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT "Conflict exit handler";
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_insert_insert_conflict_with_exit_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 0 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
--connection node_1
|
||||
|
||||
#
|
||||
# Case 3c: Two INSERTs are run inside stored procedure, this time
|
||||
# the first INSERT will have a BF abort and real conflict.
|
||||
# A CONTINUE HANDLER is declared for the procedure. The expected outcome
|
||||
# is that the the first INSERT fails but the second is executed without
|
||||
# errors. wsrep_local_replays is not incremented.
|
||||
#
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE proc_insert_insert_conflict_with_continue_handler()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT "Conflict continue handler";
|
||||
INSERT INTO t1 VALUES (2, 'd');
|
||||
INSERT INTO t1 VALUES (4, 'd');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
INSERT INTO t1 VALUES (1, 'a'), (3, 'a');
|
||||
--let $wsrep_local_replays_orig = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--let $galera_sp_bf_abort_proc = proc_insert_insert_conflict_with_continue_handler
|
||||
--let $galera_sp_bf_abort_conflict = INSERT INTO t1 VALUES (2, 'c')
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--source galera_sp_bf_abort.inc
|
||||
--connection node_1
|
||||
--reap
|
||||
SET SESSION wsrep_sync_wait = default;
|
||||
SELECT * FROM t1;
|
||||
--let $wsrep_local_replays_curr = `SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_replays'`
|
||||
--disable_query_log
|
||||
--eval SELECT $wsrep_local_replays_curr - $wsrep_local_replays_orig = 0 AS wsrep_local_replays;
|
||||
--enable_query_log
|
||||
|
||||
DELETE FROM t1;
|
||||
|
||||
|
||||
DROP PROCEDURE proc_update_insert;
|
||||
DROP PROCEDURE proc_update_insert_with_continue_handler;
|
||||
DROP PROCEDURE proc_update_insert_with_exit_handler;
|
||||
DROP PROCEDURE proc_update_insert_transaction;
|
||||
DROP PROCEDURE proc_update_insert_transaction_with_continue_handler;
|
||||
DROP PROCEDURE proc_update_insert_transaction_with_exit_handler;
|
||||
DROP PROCEDURE proc_insert_insert_conflict;
|
||||
DROP PROCEDURE proc_insert_insert_conflict_with_exit_handler;
|
||||
DROP PROCEDURE proc_insert_insert_conflict_with_continue_handler;
|
||||
DROP TABLE t1;
|
|
@ -45,6 +45,9 @@
|
|||
#include "transaction.h" // trans_commit_stmt
|
||||
#include "sql_audit.h"
|
||||
#include "debug_sync.h"
|
||||
#ifdef WITH_WSREP
|
||||
#include "wsrep_thd.h"
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/*
|
||||
Sufficient max length of printed destinations and frame offsets (all uints).
|
||||
|
@ -1318,7 +1321,93 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
|||
thd->m_digest= NULL;
|
||||
|
||||
err_status= i->execute(thd, &ip);
|
||||
#ifdef WITH_WSREP
|
||||
if (m_type == TYPE_ENUM_PROCEDURE)
|
||||
{
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
if (thd->wsrep_conflict_state == MUST_REPLAY)
|
||||
{
|
||||
wsrep_replay_sp_transaction(thd);
|
||||
err_status= thd->get_stmt_da()->is_set();
|
||||
thd->wsrep_conflict_state= NO_CONFLICT;
|
||||
}
|
||||
else if (thd->wsrep_conflict_state == ABORTED ||
|
||||
thd->wsrep_conflict_state == CERT_FAILURE)
|
||||
{
|
||||
/*
|
||||
If the statement execution was BF aborted or was aborted
|
||||
due to certification failure, clean up transaction here
|
||||
and reset conflict state to NO_CONFLICT and thd->killed
|
||||
to THD::NOT_KILLED. Error handling is done based on err_status
|
||||
below. Error must have been raised by wsrep hton code before
|
||||
entering here.
|
||||
*/
|
||||
DBUG_ASSERT(err_status);
|
||||
DBUG_ASSERT(thd->get_stmt_da()->is_error());
|
||||
thd->wsrep_conflict_state= NO_CONFLICT;
|
||||
thd->killed= NOT_KILLED;
|
||||
}
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
#ifdef WITH_WSREP_NO
|
||||
if (WSREP(thd))
|
||||
{
|
||||
if (((thd->wsrep_trx().state() == wsrep::transaction::s_executing) &&
|
||||
(thd->is_fatal_error || thd->killed)))
|
||||
{
|
||||
WSREP_DEBUG("SP abort err status %d in sub %d trx state %d",
|
||||
err_status, thd->in_sub_stmt, thd->wsrep_trx().state());
|
||||
err_status= 1;
|
||||
thd->is_fatal_error= 1;
|
||||
/*
|
||||
SP was killed, and it is not due to a wsrep conflict.
|
||||
We skip after_command hook at this point because
|
||||
otherwise it clears the error, and cleans up the
|
||||
whole transaction. For now we just return and finish
|
||||
our handling once we are back to mysql_parse.
|
||||
*/
|
||||
WSREP_DEBUG("Skipping after_command hook for killed SP");
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool must_replay= wsrep_must_replay(thd);
|
||||
if (must_replay)
|
||||
{
|
||||
WSREP_DEBUG("MUST_REPLAY set after SP, err_status %d trx state: %d",
|
||||
err_status, thd->wsrep_trx().state());
|
||||
}
|
||||
(void) wsrep_after_statement(thd);
|
||||
|
||||
/*
|
||||
Reset the return code to zero if the transaction was
|
||||
replayed succesfully.
|
||||
*/
|
||||
if (must_replay && !wsrep_current_error(thd))
|
||||
{
|
||||
err_status= 0;
|
||||
thd->get_stmt_da()->reset_diagnostics_area();
|
||||
}
|
||||
/*
|
||||
Final wsrep error status for statement is known only after
|
||||
wsrep_after_statement() call. If the error is set, override
|
||||
error in thd diagnostics area and reset wsrep client_state error
|
||||
so that the error does not get propagated via client-server protocol.
|
||||
*/
|
||||
if (wsrep_current_error(thd))
|
||||
{
|
||||
wsrep_override_error(thd, wsrep_current_error(thd),
|
||||
wsrep_current_error_status(thd));
|
||||
thd->wsrep_cs().reset_error();
|
||||
/* Reset also thd->killed if it has been set during BF abort. */
|
||||
if (thd->killed == KILL_QUERY)
|
||||
thd->killed= NOT_KILLED;
|
||||
/* if failed transaction was not replayed, must return with error from here */
|
||||
if (!must_replay) err_status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
thd->m_digest= parent_digest;
|
||||
|
||||
if (i->free_list)
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#include "sql_handler.h" // mysql_ha_rm_tables
|
||||
#include "sp_cache.h" // sp_invalidate_cache
|
||||
#include <mysys_err.h>
|
||||
#ifdef WITH_WSREP
|
||||
#include "debug_sync.h"
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, uint length,
|
||||
MEM_ROOT *mem_root)
|
||||
|
@ -517,7 +520,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||
|
||||
#ifdef WITH_WSREP
|
||||
if (thd->wsrep_exec_mode == LOCAL_STATE)
|
||||
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
|
||||
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, tables);
|
||||
#endif
|
||||
|
||||
/* We should have only one table in table list. */
|
||||
|
@ -579,6 +582,16 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||
goto end;
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
DBUG_EXECUTE_IF("sync.mdev_20225",
|
||||
{
|
||||
const char act[]=
|
||||
"now "
|
||||
"wait_for signal.mdev_20225_continue";
|
||||
DBUG_ASSERT(!debug_sync_set_action(thd,
|
||||
STRING_WITH_LEN(act)));
|
||||
};);
|
||||
#endif /* WITH_WSREP */
|
||||
result= (create ?
|
||||
table->triggers->create_trigger(thd, tables, &stmt_query):
|
||||
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
||||
|
|
|
@ -37,6 +37,8 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd);
|
|||
void wsrep_cleanup_transaction(THD *thd)
|
||||
{
|
||||
if (!WSREP(thd)) return;
|
||||
DBUG_ASSERT(thd->wsrep_conflict_state != MUST_REPLAY &&
|
||||
thd->wsrep_conflict_state != REPLAYING);
|
||||
|
||||
if (wsrep_emulate_bin_log) thd_binlog_trx_reset(thd);
|
||||
thd->wsrep_ws_handle.trx_id= WSREP_UNDEFINED_TRX_ID;
|
||||
|
@ -137,7 +139,11 @@ void wsrep_post_commit(THD* thd, bool all)
|
|||
/* non-InnoDB statements may have populated events in stmt cache
|
||||
=> cleanup
|
||||
*/
|
||||
WSREP_DEBUG("cleanup transaction for LOCAL_STATE");
|
||||
if (thd->wsrep_conflict_state != MUST_REPLAY)
|
||||
{
|
||||
WSREP_DEBUG("cleanup transaction for LOCAL_STATE: %s",
|
||||
WSREP_QUERY(thd));
|
||||
}
|
||||
/*
|
||||
Run post-rollback hook to clean up in the case if
|
||||
some keys were populated for the transaction in provider
|
||||
|
@ -146,13 +152,18 @@ void wsrep_post_commit(THD* thd, bool all)
|
|||
rolls back to savepoint after first operation.
|
||||
*/
|
||||
if (all && thd->wsrep_conflict_state != MUST_REPLAY &&
|
||||
wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle))
|
||||
thd->wsrep_conflict_state != REPLAYING &&
|
||||
wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle))
|
||||
{
|
||||
WSREP_WARN("post_rollback fail: %llu %d",
|
||||
(long long)thd->thread_id, thd->get_stmt_da()->status());
|
||||
}
|
||||
wsrep_cleanup_transaction(thd);
|
||||
break;
|
||||
if (thd->wsrep_conflict_state != MUST_REPLAY &&
|
||||
thd->wsrep_conflict_state != REPLAYING)
|
||||
{
|
||||
wsrep_cleanup_transaction(thd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
@ -566,7 +577,8 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
|
|||
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
|
||||
/* fall through */
|
||||
case WSREP_TRX_FAIL:
|
||||
WSREP_DEBUG("commit failed for reason: %d", rcode);
|
||||
WSREP_DEBUG("commit failed for reason: %d conf %d",
|
||||
rcode, thd->wsrep_conflict_state);
|
||||
DBUG_PRINT("wsrep", ("replicating commit fail"));
|
||||
|
||||
wsrep_thd_set_query_state(thd, QUERY_EXEC);
|
||||
|
|
|
@ -1612,7 +1612,6 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
|
|||
|
||||
case SQLCOM_CREATE_TRIGGER:
|
||||
|
||||
DBUG_ASSERT(!table_list);
|
||||
DBUG_ASSERT(first_table);
|
||||
|
||||
if (thd->find_temporary_table(first_table))
|
||||
|
@ -1621,6 +1620,14 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
|
|||
}
|
||||
return true;
|
||||
|
||||
case SQLCOM_DROP_TRIGGER:
|
||||
DBUG_ASSERT(table_list);
|
||||
if (thd->find_temporary_table(table_list))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
if (table && !thd->find_temporary_table(db, table))
|
||||
{
|
||||
|
|
111
sql/wsrep_thd.cc
111
sql/wsrep_thd.cc
|
@ -93,10 +93,12 @@ void wsrep_client_rollback(THD *thd)
|
|||
#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1
|
||||
#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2
|
||||
|
||||
static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
|
||||
static rpl_group_info* wsrep_relay_group_init(THD *thd, const char* log_fname)
|
||||
{
|
||||
Relay_log_info* rli= new Relay_log_info(false);
|
||||
|
||||
WSREP_DEBUG("wsrep_relay_group_init %s", log_fname);
|
||||
|
||||
if (!rli->relay_log.description_event_for_exec)
|
||||
{
|
||||
rli->relay_log.description_event_for_exec=
|
||||
|
@ -125,7 +127,7 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
|
|||
rli->mi = new Master_info(&connection_name, false);
|
||||
|
||||
struct rpl_group_info *rgi= new rpl_group_info(rli);
|
||||
rgi->thd= rli->sql_driver_thd= current_thd;
|
||||
rgi->thd= rli->sql_driver_thd= thd;
|
||||
|
||||
if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()))
|
||||
{
|
||||
|
@ -150,7 +152,7 @@ static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow)
|
|||
else
|
||||
thd->variables.option_bits&= ~(OPTION_BIN_LOG);
|
||||
|
||||
if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay");
|
||||
if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init(thd, "wsrep_relay");
|
||||
|
||||
/* thd->system_thread_info.rpl_sql_info isn't initialized. */
|
||||
if (!thd->slave_thread)
|
||||
|
@ -193,6 +195,109 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow)
|
|||
thd->set_row_count_func(shadow->row_count_func);
|
||||
}
|
||||
|
||||
void wsrep_replay_sp_transaction(THD* thd)
|
||||
{
|
||||
DBUG_ENTER("wsrep_replay_sp_transaction");
|
||||
mysql_mutex_assert_owner(&thd->LOCK_thd_data);
|
||||
DBUG_ASSERT(thd->wsrep_conflict_state == MUST_REPLAY);
|
||||
DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0);
|
||||
|
||||
WSREP_DEBUG("replaying SP transaction %llu", thd->thread_id);
|
||||
close_thread_tables(thd);
|
||||
if (thd->locked_tables_mode && thd->lock)
|
||||
{
|
||||
WSREP_DEBUG("releasing table lock for replaying (%u)",
|
||||
thd->thread_id);
|
||||
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
|
||||
}
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
THD *replay_thd= new THD(true);
|
||||
replay_thd->thread_stack= thd->thread_stack;
|
||||
|
||||
struct wsrep_thd_shadow shadow;
|
||||
wsrep_prepare_bf_thd(replay_thd, &shadow);
|
||||
WSREP_DEBUG("replaying set for %p rgi %p", replay_thd, replay_thd->wsrep_rgi); replay_thd->wsrep_trx_meta= thd->wsrep_trx_meta;
|
||||
replay_thd->wsrep_ws_handle= thd->wsrep_ws_handle;
|
||||
replay_thd->wsrep_ws_handle.trx_id= WSREP_UNDEFINED_TRX_ID;
|
||||
replay_thd->wsrep_conflict_state= REPLAYING;
|
||||
|
||||
replay_thd->variables.option_bits|= OPTION_BEGIN;
|
||||
replay_thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
|
||||
thd->reset_globals();
|
||||
replay_thd->store_globals();
|
||||
wsrep_status_t rcode= wsrep->replay_trx(wsrep,
|
||||
&replay_thd->wsrep_ws_handle,
|
||||
(void*) replay_thd);
|
||||
|
||||
wsrep_return_from_bf_mode(replay_thd, &shadow);
|
||||
replay_thd->reset_globals();
|
||||
delete replay_thd;
|
||||
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
|
||||
thd->store_globals();
|
||||
|
||||
switch (rcode)
|
||||
{
|
||||
case WSREP_OK:
|
||||
{
|
||||
thd->wsrep_conflict_state= NO_CONFLICT;
|
||||
thd->killed= NOT_KILLED;
|
||||
wsrep_status_t rcode= wsrep->post_commit(wsrep, &thd->wsrep_ws_handle);
|
||||
if (rcode != WSREP_OK)
|
||||
{
|
||||
WSREP_WARN("Post commit failed for SP replay: thd: %u error: %d",
|
||||
thd->thread_id, rcode);
|
||||
}
|
||||
/* As replaying the transaction was successful, an error must not
|
||||
be returned to client, so we need to reset the error state of
|
||||
the diagnostics area */
|
||||
thd->get_stmt_da()->reset_diagnostics_area();
|
||||
break;
|
||||
}
|
||||
case WSREP_TRX_FAIL:
|
||||
{
|
||||
thd->wsrep_conflict_state= ABORTED;
|
||||
wsrep_status_t rcode= wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle);
|
||||
if (rcode != WSREP_OK)
|
||||
{
|
||||
WSREP_WARN("Post rollback failed for SP replay: thd: %u error: %d",
|
||||
thd->thread_id, rcode);
|
||||
}
|
||||
if (thd->get_stmt_da()->is_set())
|
||||
{
|
||||
thd->get_stmt_da()->reset_diagnostics_area();
|
||||
}
|
||||
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
|
||||
rcode,
|
||||
(thd->db ? thd->db : "(null)"),
|
||||
WSREP_QUERY(thd));
|
||||
/* we're now in inconsistent state, must abort */
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
unireg_abort(1);
|
||||
break;
|
||||
}
|
||||
|
||||
wsrep_cleanup_transaction(thd);
|
||||
|
||||
mysql_mutex_lock(&LOCK_wsrep_replaying);
|
||||
wsrep_replaying--;
|
||||
WSREP_DEBUG("replaying decreased: %d, thd: %u",
|
||||
wsrep_replaying, thd->thread_id);
|
||||
mysql_cond_broadcast(&COND_wsrep_replaying);
|
||||
mysql_mutex_unlock(&LOCK_wsrep_replaying);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void wsrep_replay_transaction(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("wsrep_replay_transaction");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff,
|
||||
enum enum_var_type scope);
|
||||
void wsrep_client_rollback(THD *thd);
|
||||
void wsrep_replay_sp_transaction(THD* thd);
|
||||
void wsrep_replay_transaction(THD *thd);
|
||||
bool wsrep_create_appliers(long threads, bool thread_count_lock=false);
|
||||
void wsrep_create_rollbacker();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# This group is read both both by the client and the server
|
||||
# This group is read both by the client and the server
|
||||
# use it for options that affect everything
|
||||
#
|
||||
[client-server]
|
||||
|
|
Loading…
Add table
Reference in a new issue