summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2017-09-13 19:51:30 +0300
committerJan Lindström <jan.lindstrom@mariadb.com>2017-09-15 13:54:39 +0300
commit926ed981c608ff2d72cd6d1ee36dcfbd25c51104 (patch)
tree04d1325ed686be5d9db23b3f88ed4f6f3b827bda
parentc9da448ef03a196a529164e20869441b268900af (diff)
downloadmariadb-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.result50
-rw-r--r--storage/innobase/row/row0upd.cc38
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);