diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2017-09-13 19:51:30 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2017-09-15 13:54:39 +0300 |
commit | 926ed981c608ff2d72cd6d1ee36dcfbd25c51104 (patch) | |
tree | 04d1325ed686be5d9db23b3f88ed4f6f3b827bda | |
parent | c9da448ef03a196a529164e20869441b268900af (diff) | |
download | mariadb-git-bb-10.2-MDEV-13678.tar.gz |
MDEV-13678: DELETE with CASCADE takes a long time when Galera is enabledbb-10.2-MDEV-13678
Ported fix from mysql-wsrep-bugs with some refactoring.
Test case is MW-402 where MariaDB needs record as there is
extra connection <con_name> lines.
-rw-r--r-- | mysql-test/suite/galera/r/MW-402.result | 50 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.cc | 38 |
2 files changed, 61 insertions, 27 deletions
diff --git a/mysql-test/suite/galera/r/MW-402.result b/mysql-test/suite/galera/r/MW-402.result index 4261bc6bac3..81d6f1a555e 100644 --- a/mysql-test/suite/galera/r/MW-402.result +++ b/mysql-test/suite/galera/r/MW-402.result @@ -1,26 +1,37 @@ +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON DELETE CASCADE); INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1, 0); +connection node_1a; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE c SET f2=1 where f1=1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; DELETE FROM p WHERE f1 = 1; +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,local_monitor_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 2 0 @@ -28,29 +39,39 @@ SELECT * FROM c; f1 p_id f2 DROP TABLE c; DROP TABLE p; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE); INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1, 0); +connection node_1a; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE c SET f2=2 where f1=1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; UPDATE p set f1=11 WHERE f1 = 1; +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,local_monitor_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 2 0 @@ -60,29 +81,39 @@ f1 p_id f2 1 11 0 DROP TABLE c; DROP TABLE p; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE); INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1, 0); +connection node_1a; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE c SET p_id=2 where f1=1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; UPDATE p set f1=11 WHERE f1 = 1; +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,local_monitor_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 2 0 @@ -90,23 +121,32 @@ f1 f2 SELECT * FROM c; f1 p_id f2 1 11 0 +connection node_1a; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p set f1=21 WHERE f1 = 11; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; UPDATE c SET p_id=2 where f1=1; +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,local_monitor_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 2 0 @@ -116,6 +156,7 @@ f1 p_id f2 1 2 0 DROP TABLE c; DROP TABLE p; +connection node_1; CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER, @@ -124,22 +165,31 @@ CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)); INSERT INTO p1 VALUES (1, 0); INSERT INTO p2 VALUES (1, 0); INSERT INTO c VALUES (1, 1, 1, 0); +connection node_1a; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p2 SET f2=2 where f1=1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; DELETE FROM p1 WHERE f1 = 1; +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,local_monitor_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +connection node_2; SELECT * FROM p1; f1 f2 SELECT * FROM p2; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index df70efae6a5..e92283d5590 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -460,7 +460,7 @@ func_exit: @param[in] node query node @param[in] trx transaction @return whether the node cannot be ignored */ -static +inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) { @@ -469,10 +469,9 @@ wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) return false; } - const upd_cascade_t& nodes = *static_cast<const upd_node_t*>( - node->common.parent)->cascade_upd_nodes; - const upd_cascade_t::const_iterator end = nodes.end(); - return std::find(nodes.begin(), end, node) == end; + const upd_node_t* parent = static_cast<const upd_node_t*>(node->common.parent); + + return parent->cascade_upd_nodes->empty(); } #endif /* WITH_WSREP */ @@ -2435,10 +2434,6 @@ row_upd_sec_index_entry( if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ - err = btr_cur_del_mark_set_sec_rec( flags, btr_cur, TRUE, thr, &mtr); @@ -2447,11 +2442,9 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP if (!referenced && foreign && - wsrep_on(trx->mysql_thd) && - !wsrep_thd_is_BF(trx->mysql_thd, FALSE) && - (!parent || (que_node_get_type(parent) != - QUE_NODE_UPDATE) || - ((upd_node_t*)parent)->cascade_upd_nodes->empty())) { + wsrep_must_process_fk(node, trx) && + !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + ulint* offsets = rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, &heap); @@ -2670,9 +2663,6 @@ row_upd_clust_rec_by_insert( rec_t* rec; ulint* offsets = NULL; -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2760,9 +2750,8 @@ check_fk: goto err_exit; } #ifdef WITH_WSREP - } else if (foreign && wsrep_on(trx->mysql_thd) && - (!parent || (que_node_get_type(parent) != QUE_NODE_UPDATE) || - ((upd_node_t*)parent)->cascade_upd_nodes->empty())) { + } else if (foreign && + wsrep_must_process_fk(node, trx)) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); @@ -2979,10 +2968,6 @@ row_upd_del_mark_clust_rec( ut_ad(dict_index_is_clust(index)); ut_ad(node->is_delete); -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ - pcur = node->pcur; btr_cur = btr_pcur_get_btr_cur(pcur); @@ -3008,9 +2993,8 @@ row_upd_del_mark_clust_rec( err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); #ifdef WITH_WSREP - } else if (trx && wsrep_on(trx->mysql_thd) && - (!parent || (que_node_get_type(parent) != QUE_NODE_UPDATE) || - ((upd_node_t*)parent)->cascade_upd_nodes->empty())) { + } else if (trx && + wsrep_must_process_fk(node, trx)) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); |