diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result index 73375ae55c5..a6c6504dc39 100644 --- a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result +++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result @@ -1,3 +1,8 @@ +# +# test phase with cascading foreign key through 3 tables +# +connection node_1; +set wsrep_sync_wait=0; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY ) ENGINE=InnoDB; @@ -19,14 +24,15 @@ INSERT INTO grandparent VALUES (1),(2); INSERT INTO parent VALUES (1,1), (2,2); INSERT INTO child VALUES (1,1), (2,2); connection node_2; +set wsrep_sync_wait=0; DELETE FROM grandparent WHERE id = 1; connection node_1; -SELECT COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; -COUNT(*) = 0 -1 -SELECT COUNT(*) = 0 FROM child WHERE parent_id = 1; -COUNT(*) = 0 -1 +SELECT COUNT(*), COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child WHERE parent_id = 1; +COUNT(*) COUNT(*) = 0 +0 1 DROP TABLE child; DROP TABLE parent; DROP TABLE grandparent; diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result new file mode 100644 index 00000000000..89613b2856a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete_debug.result @@ -0,0 +1,67 @@ +# +# test phase with foreign key of varchar type +# +connection node_1; +CREATE TABLE parent ( +`id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE TABLE child ( +`id` int NOT NULL, +`parent_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `parent_id` (`parent_id`), +CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +INSERT INTO parent VALUES ('row one'), ('row two'); +INSERT INTO child VALUES (1,'row one'), (2,'row two'); +connection node_2; +DELETE FROM parent; +connection node_1; +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child; +COUNT(*) COUNT(*) = 0 +0 1 +DROP TABLE child; +DROP TABLE parent; +# +# test phase with MM conflict in FK cascade +# +connection node_1; +set wsrep_retry_autocommit=0; +CREATE TABLE parent ( +id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; +CREATE TABLE child ( +id INT NOT NULL PRIMARY KEY, +j int default 0, +parent_id INT, +FOREIGN KEY (parent_id) +REFERENCES parent(id) +ON DELETE CASCADE +) ENGINE=InnoDB; +INSERT INTO parent VALUES (1); +INSERT INTO child VALUES (1,0,1); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; +connection node_2; +DELETE FROM parent; +connection node_1a; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_1; +update child set j=2;; +connection node_1a; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; +connection node_1; +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +COUNT(*) COUNT(*) = 0 +0 1 +SELECT COUNT(*), COUNT(*) = 0 FROM child; +COUNT(*) COUNT(*) = 0 +0 1 +DROP TABLE child; +DROP TABLE parent; diff --git a/mysql-test/suite/galera/t/galera_fk_cascade_delete.test b/mysql-test/suite/galera/t/galera_fk_cascade_delete.test index 9b79b4c30b6..6f0de0a1f4a 100644 --- a/mysql-test/suite/galera/t/galera_fk_cascade_delete.test +++ b/mysql-test/suite/galera/t/galera_fk_cascade_delete.test @@ -3,7 +3,13 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc + +--echo # +--echo # test phase with cascading foreign key through 3 tables +--echo # + +--connection node_1 +set wsrep_sync_wait=0; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY @@ -30,11 +36,17 @@ INSERT INTO parent VALUES (1,1), (2,2); INSERT INTO child VALUES (1,1), (2,2); --connection node_2 +set wsrep_sync_wait=0; + +--let $wait_condition = SELECT COUNT(*) = 2 FROM child; +--source include/wait_condition.inc DELETE FROM grandparent WHERE id = 1; --connection node_1 -SELECT COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; -SELECT COUNT(*) = 0 FROM child WHERE parent_id = 1; +--let $wait_condition = SELECT COUNT(*) = 1 FROM child; +--source include/wait_condition.inc +SELECT COUNT(*), COUNT(*) = 0 FROM parent WHERE grandparent_id = 1; +SELECT COUNT(*), COUNT(*) = 0 FROM child WHERE parent_id = 1; DROP TABLE child; DROP TABLE parent; diff --git a/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test b/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test new file mode 100644 index 00000000000..f38c028b7d6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_fk_cascade_delete_debug.test @@ -0,0 +1,98 @@ +--source include/galera_cluster.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--echo # +--echo # test phase with foreign key of varchar type +--echo # +--connection node_1 + CREATE TABLE parent ( + `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + + CREATE TABLE child ( + `id` int NOT NULL, + `parent_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `parent_id` (`parent_id`), + CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +INSERT INTO parent VALUES ('row one'), ('row two'); +INSERT INTO child VALUES (1,'row one'), (2,'row two'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM child; +--source include/wait_condition.inc +DELETE FROM parent; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM child; +--source include/wait_condition.inc + +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +SELECT COUNT(*), COUNT(*) = 0 FROM child; + +DROP TABLE child; +DROP TABLE parent; + +--echo # +--echo # test phase with MM conflict in FK cascade +--echo # + +--connection node_1 +set wsrep_retry_autocommit=0; +CREATE TABLE parent ( + id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; + +CREATE TABLE child ( + id INT NOT NULL PRIMARY KEY, + j int default 0, + parent_id INT, + FOREIGN KEY (parent_id) + REFERENCES parent(id) + ON DELETE CASCADE +) ENGINE=InnoDB; + +INSERT INTO parent VALUES (1); +INSERT INTO child VALUES (1,0,1); + +# block applier before applying +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM child; +--source include/wait_condition.inc +DELETE FROM parent; + +--connection node_1a +# wait until applier has reached the sync point +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + + +--connection node_1 +# issue conflicting write to child table, it should fail in certification +--error ER_LOCK_DEADLOCK +--send update child set j=2; + +--connection node_1a +# release the applier +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "RESET"; + +--connection node_1 +--reap + +--let $wait_condition = SELECT COUNT(*) = 0 FROM child; +--source include/wait_condition.inc +SELECT COUNT(*), COUNT(*) = 0 FROM parent; +SELECT COUNT(*), COUNT(*) = 0 FROM child; + +DROP TABLE child; +DROP TABLE parent; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 50394193a15..c0aa3655b7b 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1402,20 +1402,20 @@ row_ins_foreign_check_on_constraint( btr_pcur_store_position(cascade->pcur, mtr); } +#ifdef WITH_WSREP + err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, + FALSE, WSREP_KEY_EXCLUSIVE); + if (err != DB_SUCCESS) { + ib::info() << "WSREP: foreign key append failed: " << err; + goto nonstandard_exit_func; + } +#endif /* WITH_WSREP */ mtr_commit(mtr); ut_a(cascade->pcur->rel_pos == BTR_PCUR_ON); cascade->state = UPD_NODE_UPDATE_CLUSTERED; -#ifdef WITH_WSREP - err = wsrep_append_foreign_key(trx, foreign, cascade->pcur->old_rec, clust_index, - FALSE, WSREP_KEY_EXCLUSIVE); - if (err != DB_SUCCESS) { - fprintf(stderr, - "WSREP: foreign key append failed: %d\n", err); - } else -#endif /* WITH_WSREP */ err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table);