diff --git a/include/wsrep.h b/include/wsrep.h index 65cceba1065..5272b687732 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -23,15 +23,17 @@ #define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) #define WSREP_MYSQL_DB (char *)"mysql" -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ +#define WSREP_TO_ISOLATION_BEGIN_IF(db_, table_, table_list_) \ + if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) + +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \ goto wsrep_error_label; #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_) \ if (WSREP(thd) && wsrep_thd_is_local(thd) && \ wsrep_to_isolation_begin(thd, db_, table_, \ - table_list_, alter_info_, fk_tables_)) \ - goto wsrep_error_label; + table_list_, alter_info_, fk_tables_)) #define WSREP_TO_ISOLATION_END \ if ((WSREP(thd) && wsrep_thd_is_local_toi(thd)) || \ @@ -48,7 +50,7 @@ #define WSREP_TO_ISOLATION_BEGIN_FK_TABLES(db_, table_, table_list_, fk_tables) \ if (WSREP(thd) && !thd->lex->no_write_to_binlog \ - && wsrep_to_isolation_begin(thd, db_, table_, table_list_, NULL, fk_tables)) goto wsrep_error_label; + && wsrep_to_isolation_begin(thd, db_, table_, table_list_, NULL, fk_tables)) #define WSREP_DEBUG(...) \ if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) diff --git a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result index a39fa6a6219..f0d0d61e58f 100644 --- a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result +++ b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result @@ -3,6 +3,9 @@ connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; SET SESSION wsrep_sync_wait=0; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1b; +SET SESSION wsrep_sync_wait=0; ###################################################################### # Test for OPTIMIZE ###################################################################### @@ -14,29 +17,39 @@ SET SESSION wsrep_sync_wait=0; ###################################################################### connection node_1; SET SESSION wsrep_sync_wait=0; -CREATE TABLE p (pk INTEGER PRIMARY KEY, f2 CHAR(30)); -INSERT INTO p VALUES (1, 'INITIAL VALUE'); -INSERT INTO p VALUES (2, 'INITIAL VALUE'); -CREATE TABLE c (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p(pk)); -INSERT INTO c VALUES (1,1), (2,2); +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; connection node_2; SET SESSION wsrep_sync_wait=0; -OPTIMIZE TABLE c ; +OPTIMIZE TABLE c1 ; Table Op Msg_type Msg_text -test.c optimize note Table does not support optimize, doing recreate + analyze instead -test.c optimize status OK +test.c1 optimize note Table does not support optimize, doing recreate + analyze instead +test.c1 optimize status OK connection node_1; COMMIT; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 ###################################################################### @@ -49,16 +62,16 @@ connection node_1; BEGIN; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; connection node_2; -OPTIMIZE TABLE c ; +OPTIMIZE TABLE c1 ; Table Op Msg_type Msg_text -test.c optimize note Table does not support optimize, doing recreate + analyze instead -test.c optimize status OK +test.c1 optimize note Table does not support optimize, doing recreate + analyze instead +test.c1 optimize status OK connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; COMMIT; connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; @@ -67,15 +80,73 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT 'I deadlocked'; I deadlocked I deadlocked -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 -DROP TABLE c; -DROP TABLE p; +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +OPTIMIZE TABLE c2 ; +Table Op Msg_type Msg_text +test.c2 optimize note Table does not support optimize, doing recreate + analyze instead +test.c2 optimize status OK +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE c1, c2; +DROP TABLE p1, p2; ###################################################################### # Test for REPAIR ###################################################################### @@ -87,28 +158,38 @@ DROP TABLE p; ###################################################################### connection node_1; SET SESSION wsrep_sync_wait=0; -CREATE TABLE p (pk INTEGER PRIMARY KEY, f2 CHAR(30)); -INSERT INTO p VALUES (1, 'INITIAL VALUE'); -INSERT INTO p VALUES (2, 'INITIAL VALUE'); -CREATE TABLE c (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p(pk)); -INSERT INTO c VALUES (1,1), (2,2); +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; connection node_2; SET SESSION wsrep_sync_wait=0; -REPAIR TABLE c ; +REPAIR TABLE c1 ; Table Op Msg_type Msg_text -test.c repair note The storage engine for the table doesn't support repair +test.c1 repair note The storage engine for the table doesn't support repair connection node_1; COMMIT; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 ###################################################################### @@ -121,15 +202,15 @@ connection node_1; BEGIN; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; connection node_2; -REPAIR TABLE c ; +REPAIR TABLE c1 ; Table Op Msg_type Msg_text -test.c repair note The storage engine for the table doesn't support repair +test.c1 repair note The storage engine for the table doesn't support repair connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; COMMIT; connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; @@ -138,15 +219,72 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT 'I deadlocked'; I deadlocked I deadlocked -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 -DROP TABLE c; -DROP TABLE p; +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +REPAIR TABLE c2 ; +Table Op Msg_type Msg_text +test.c2 repair note The storage engine for the table doesn't support repair +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE c1, c2; +DROP TABLE p1, p2; ###################################################################### # Test for ALTER ENGINE=INNODB ###################################################################### @@ -158,26 +296,36 @@ DROP TABLE p; ###################################################################### connection node_1; SET SESSION wsrep_sync_wait=0; -CREATE TABLE p (pk INTEGER PRIMARY KEY, f2 CHAR(30)); -INSERT INTO p VALUES (1, 'INITIAL VALUE'); -INSERT INTO p VALUES (2, 'INITIAL VALUE'); -CREATE TABLE c (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p(pk)); -INSERT INTO c VALUES (1,1), (2,2); +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; connection node_2; SET SESSION wsrep_sync_wait=0; -ALTER TABLE c ENGINE=INNODB; +ALTER TABLE c1 ENGINE=INNODB; connection node_1; COMMIT; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 ###################################################################### @@ -190,13 +338,13 @@ connection node_1; BEGIN; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; connection node_2; -ALTER TABLE c ENGINE=INNODB; +ALTER TABLE c1 ENGINE=INNODB; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; COMMIT; connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; @@ -205,12 +353,199 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT 'I deadlocked'; I deadlocked I deadlocked -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 connection node_2; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 -DROP TABLE c; -DROP TABLE p; +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +ALTER TABLE c2 ENGINE=INNODB; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE c1, c2; +DROP TABLE p1, p2; +###################################################################### +# Test for TRUNCATE +###################################################################### +###################################################################### +# +# Scenario #1: DML working on FK parent table BF aborted by DDL +# over child table +# +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +connection node_2; +SET SESSION wsrep_sync_wait=0; +TRUNCATE TABLE c1 ; +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +###################################################################### +# +# Scenario #2: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +TRUNCATE TABLE c1 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +TRUNCATE TABLE c2 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE c1, c2; +DROP TABLE p1, p2; diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc index 18271d0b641..4a473d3776c 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc @@ -40,31 +40,40 @@ --connection node_1 SET SESSION wsrep_sync_wait=0; -CREATE TABLE p (pk INTEGER PRIMARY KEY, f2 CHAR(30)); -INSERT INTO p VALUES (1, 'INITIAL VALUE'); -INSERT INTO p VALUES (2, 'INITIAL VALUE'); +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); -CREATE TABLE c (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p(pk)); -INSERT INTO c VALUES (1,1), (2,2); + +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); + +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); + +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); --connection node_1 SET AUTOCOMMIT=ON; START TRANSACTION; -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; --connection node_2 SET SESSION wsrep_sync_wait=0; ---eval $table_admin_command TABLE c $table_admin_command_end +--eval $table_admin_command TABLE c1 $table_admin_command_end --connection node_1 --error ER_LOCK_DEADLOCK COMMIT; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; --connection node_2 -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; --echo ###################################################################### --echo # @@ -81,7 +90,7 @@ BEGIN; --source include/galera_set_sync_point.inc --connection node_2 ---eval $table_admin_command TABLE c $table_admin_command_end +--eval $table_admin_command TABLE c1 $table_admin_command_end --connection node_1a --source include/galera_wait_sync_point.inc @@ -89,7 +98,7 @@ BEGIN; --let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` --connection node_1 -UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; --send COMMIT --connection node_1a @@ -105,10 +114,71 @@ UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1; SELECT 'I deadlocked'; -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; --connection node_2 -SELECT COUNT(*) AS EXPECT_2 FROM p WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; -DROP TABLE c; -DROP TABLE p; + +--echo ###################################################################### +--echo # +--echo # Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +--echo # but fails in certification for earlier DDL on child table +--echo # which is child to both FK parents +--echo # +--echo ###################################################################### + +--connection node_1 +BEGIN; + +--connection node_1b +BEGIN; + +# Block the applier on node #1 and issue DDL on node 2 +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_2 +--eval $table_admin_command TABLE c2 $table_admin_command_end + +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +--let $expected_cert_failures = `SELECT VARIABLE_VALUE+2 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + +--connection node_1 +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +--send COMMIT + +--connection node_1b +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +--send COMMIT + +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap +SELECT 'I deadlocked'; + +--connection node_1b +--error ER_LOCK_DEADLOCK +--reap +SELECT 'I deadlocked'; + +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; + +DROP TABLE c1, c2; +DROP TABLE p1, p2; diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test index a07006a8e49..c6d20e3bffd 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test @@ -7,10 +7,16 @@ --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc +# sync point controlling session --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a SET SESSION wsrep_sync_wait=0; +# secondary conflicting DML victim session +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b +SET SESSION wsrep_sync_wait=0; + --let $table_admin_command = OPTIMIZE --source galera_ddl_fk_conflict.inc @@ -21,5 +27,9 @@ SET SESSION wsrep_sync_wait=0; --let $table_admin_command_end = ENGINE=INNODB --source galera_ddl_fk_conflict.inc +--let $table_admin_command = TRUNCATE +--let $table_admin_command_end = +--source galera_ddl_fk_conflict.inc + # CHECK and ANALYZE are not affected diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index ebd0e9b39aa..c13d61d9f7a 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -453,7 +453,9 @@ static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables) { WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, tables); } else { - WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, tables, &keys); + WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, tables, &keys) { + return true; + } } return false; diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index cefd37811a2..2bbc8169df2 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -480,7 +480,11 @@ bool Sql_cmd_alter_table::execute(THD *thd) WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL), (lex->name.str ? lex->name.str : NULL), - first_table, &alter_info, &keys); + first_table, &alter_info, &keys) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } thd->variables.auto_increment_offset = 1; thd->variables.auto_increment_increment = 1; @@ -522,11 +526,6 @@ bool Sql_cmd_alter_table::execute(THD *thd) lex->ignore); DBUG_RETURN(result); -#ifdef WITH_WSREP -wsrep_error_label: - WSREP_WARN("ALTER TABLE isolation failure"); - DBUG_RETURN(TRUE); -#endif } bool Sql_cmd_discard_import_tablespace::execute(THD *thd) diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index bfcdda6e0e9..c3d347307a2 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -416,9 +416,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) bool hton_can_recreate; #ifdef WITH_WSREP - if (WSREP(thd) && - wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0)) - DBUG_RETURN(TRUE); + if (WSREP(thd)) + { + wsrep::key_array keys; + wsrep_append_fk_parent_table(thd, table_ref, &keys); + if (keys.empty()) + { + WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL) + { + DBUG_RETURN(TRUE); + } + } else { + WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys) + { + DBUG_RETURN(TRUE); + } + } + } #endif /* WITH_WSREP */ if (lock_table(thd, table_ref, &hton_can_recreate)) DBUG_RETURN(TRUE);