diff options
author | Daniele Sciascia <daniele.sciascia@galeracluster.com> | 2022-01-13 12:51:54 +0100 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2022-01-19 15:32:42 +0200 |
commit | c75bee9478f4f2d458d3522a4bd496b95e118498 (patch) | |
tree | da4a52616c73d10e4d8001b144247f53a75e0c8f | |
parent | f8c3d5927445dcd75f31ed8e9fb3cfcc07c3ed8f (diff) | |
download | mariadb-git-c75bee9478f4f2d458d3522a4bd496b95e118498.tar.gz |
MDEV-25538 Crash on REPAIR VIEW that was created from IS tablebb-10.4-MDEV-25538
Remove calls to wsrep_append_fk_parent_table() during REPAIR/OPTIMIZE
TABLE processing. It turns out that REPAIR or OPTIMIZE commands on
table t, do not acquire MDL locks on parent tables of t (as shown in
the included test). Thus making wsrep_append_fk_parent_table()
unnecessary for OPTIMIZE and REPAIR.
This also fixes MDEV-24446 and reenables test galera.mysql-wsrep#198.
Reviewed-by: Jan Lindström <jan.lindstrom@mariadb.com>
-rw-r--r-- | mysql-test/suite/galera/disabled.def | 1 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_ddl_fk_conflict.result | 383 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_ddl_fk_no_conflict.result | 330 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_repair_view.result | 17 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ddl_fk_conflict.test | 8 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.inc | 34 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.test | 57 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_repair_view.test | 12 | ||||
-rw-r--r-- | sql/sql_admin.cc | 62 |
9 files changed, 459 insertions, 445 deletions
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 96847510273..d6cbf1a2f7f 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -32,7 +32,6 @@ galera_var_ignore_apply_errors : MDEV-26770 galera_var_ignore_apply_errors fails galera_var_node_address : MDEV-20485 Galera test failure galera_var_notify_cmd : MDEV-21905 Galera test galera_var_notify_cmd causes hang galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit -mysql-wsrep#198 : MDEV-24446: galera.mysql-wsrep#198 MTR failed: query 'reap' failed: 2000: Unknown MySQL error partition : MDEV-19958 Galera test failure on galera.partition query_cache: MDEV-15805 Test failure on galera.query_cache versioning_trx_id: MDEV-18590: galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch 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 5f09345b79b..03e84f9facd 100644 --- a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result +++ b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result @@ -7,389 +7,6 @@ connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1b; SET SESSION wsrep_sync_wait=0; ###################################################################### -# Test for OPTIMIZE -###################################################################### -###################################################################### -# -# 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; -OPTIMIZE TABLE c1 ; -Table Op Msg_type Msg_text -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_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; -OPTIMIZE TABLE c1 ; -Table Op Msg_type Msg_text -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 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; -connection node_1a; -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 OPTIMIZE -###################################################################### -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 c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); -INSERT INTO c1 VALUES (1,1); -###################################################################### -# -# Scenario #4: DML working on FK parent table tries to replicate, but -# fails in certification for earlier DDL on child table -# and another temporary table. TMP table should be skipped -# but FK child table should be replicated with proper keys -# -###################################################################### -connection node_1; -BEGIN; -SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; -connection node_2; -CREATE TEMPORARY TABLE tmp (i int); -OPTIMIZE TABLE c1, tmp ; -Table Op Msg_type Msg_text -test.c1 optimize note Table does not support optimize, doing recreate + analyze instead -test.c1 optimize status OK -test.tmp optimize note Table does not support optimize, doing recreate + analyze instead -test.tmp optimize status OK -DROP TABLE tmp; -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 -connection node_2; -SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; -EXPECT_1 -1 -DROP TABLE c1; -DROP TABLE p1; -###################################################################### -# Test for REPAIR -###################################################################### -###################################################################### -# -# 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; -REPAIR TABLE c1 ; -Table Op Msg_type Msg_text -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_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; -REPAIR TABLE c1 ; -Table Op Msg_type Msg_text -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 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; -connection node_1a; -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 REPAIR -###################################################################### -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 c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); -INSERT INTO c1 VALUES (1,1); -###################################################################### -# -# Scenario #4: DML working on FK parent table tries to replicate, but -# fails in certification for earlier DDL on child table -# and another temporary table. TMP table should be skipped -# but FK child table should be replicated with proper keys -# -###################################################################### -connection node_1; -BEGIN; -SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; -connection node_2; -CREATE TEMPORARY TABLE tmp (i int); -REPAIR TABLE c1, tmp ; -Table Op Msg_type Msg_text -test.c1 repair note The storage engine for the table doesn't support repair -test.tmp repair note The storage engine for the table doesn't support repair -DROP TABLE tmp; -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 -connection node_2; -SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; -EXPECT_1 -1 -DROP TABLE c1; -DROP TABLE p1; -###################################################################### # Test for ALTER ENGINE=INNODB ###################################################################### ###################################################################### diff --git a/mysql-test/suite/galera/r/galera_ddl_fk_no_conflict.result b/mysql-test/suite/galera/r/galera_ddl_fk_no_conflict.result new file mode 100644 index 00000000000..43046922143 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ddl_fk_no_conflict.result @@ -0,0 +1,330 @@ +connection node_2; +connection node_1; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +OPTIMIZE TABLE child;; +Table Op Msg_type Msg_text +test.child optimize note Table does not support optimize, doing recreate + analyze instead +test.child optimize status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +OPTIMIZE TABLE child;; +Table Op Msg_type Msg_text +test.child optimize note Table does not support optimize, doing recreate + analyze instead +test.child optimize status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +OPTIMIZE TABLE child;; +Table Op Msg_type Msg_text +test.child optimize note Table does not support optimize, doing recreate + analyze instead +test.child optimize status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +OPTIMIZE TABLE child;; +Table Op Msg_type Msg_text +test.child optimize note Table does not support optimize, doing recreate + analyze instead +test.child optimize status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +REPAIR TABLE child;; +Table Op Msg_type Msg_text +test.child repair note The storage engine for the table doesn't support repair +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +REPAIR TABLE child;; +Table Op Msg_type Msg_text +test.child repair note The storage engine for the table doesn't support repair +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +REPAIR TABLE child;; +Table Op Msg_type Msg_text +test.child repair note The storage engine for the table doesn't support repair +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +REPAIR TABLE child;; +Table Op Msg_type Msg_text +test.child repair note The storage engine for the table doesn't support repair +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +CHECK TABLE child;; +Table Op Msg_type Msg_text +test.child check status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +CHECK TABLE child;; +Table Op Msg_type Msg_text +test.child check status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +CHECK TABLE child;; +Table Op Msg_type Msg_text +test.child check status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +CHECK TABLE child;; +Table Op Msg_type Msg_text +test.child check status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +ANALYZE TABLE child;; +Table Op Msg_type Msg_text +test.child analyze status Engine-independent statistics collected +test.child analyze status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +ANALYZE TABLE child;; +Table Op Msg_type Msg_text +test.child analyze status Engine-independent statistics collected +test.child analyze status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +ANALYZE TABLE child;; +Table Op Msg_type Msg_text +test.child analyze status Engine-independent statistics collected +test.child analyze status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) ON UPDATE CASCADE ON DELETE CASCADE); +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); +connection node_1; +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; +pk +1 +2 +3 +4 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +ANALYZE TABLE child;; +Table Op Msg_type Msg_text +test.child analyze status Engine-independent statistics collected +test.child analyze status OK +connection node_1; +COMMIT; +DROP TABLE child, parent; +disconnect node_1a; diff --git a/mysql-test/suite/galera/r/galera_repair_view.result b/mysql-test/suite/galera/r/galera_repair_view.result new file mode 100644 index 00000000000..8dfe8c8db52 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_repair_view.result @@ -0,0 +1,17 @@ +connection node_2; +connection node_1; +CREATE TABLE t1(a int not null primary key) engine=innodb; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair note The storage engine for the table doesn't support repair +CREATE VIEW v1 AS SELECT a FROM t1; +REPAIR VIEW v1; +Table Op Msg_type Msg_text +test.v1 repair status OK +DROP VIEW v1; +DROP TABLE t1; +CREATE VIEW v1 AS SELECT table_name FROM information_schema.tables; +REPAIR VIEW v1; +Table Op Msg_type Msg_text +test.v1 repair status OK +DROP VIEW v1; 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 88837933e5a..4ec866a9f74 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test @@ -17,14 +17,6 @@ SET SESSION wsrep_sync_wait=0; --connection node_1b SET SESSION wsrep_sync_wait=0; ---let $table_admin_command = OPTIMIZE ---source galera_ddl_fk_conflict.inc ---source galera_ddl_fk_conflict_with_tmp.inc - ---let $table_admin_command = REPAIR ---source galera_ddl_fk_conflict.inc ---source galera_ddl_fk_conflict_with_tmp.inc - --let $table_admin_command = ALTER --let $table_admin_command_end = ENGINE=INNODB --source galera_ddl_fk_conflict.inc diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.inc b/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.inc new file mode 100644 index 00000000000..9e2dd391678 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.inc @@ -0,0 +1,34 @@ +# This test attempts to show that OPTIMIZE on a child table does NOT +# acquire MDL locks on the parent table. # +# param: $table_admin_command +# DDL table command to test, script will build full SQL statement: +# $table_admin_command TABLE c; +# +# param: $FK_constraint +# Foreign key constraint to use when creating the child table. +# + +CREATE TABLE parent (pk INTEGER PRIMARY KEY); +--eval CREATE TABLE child (pk INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY(parent_id) REFERENCES parent(pk) $fk_constraint) + +INSERT INTO parent VALUES (1), (2), (3), (4); +INSERT INTO child VALUES (1,1), (2,2), (3,3), (4,4); + +--connection node_1 +# Start a transaction that uses the parent table, +# so that we acquire MDL lock on parent. +START TRANSACTION; +SELECT * FROM parent FOR UPDATE; + +# In a different connection, execute the table +# admin command (OPTIMIZE / REPAIR ...) on the child table. +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--eval $table_admin_command TABLE child; + +# Expect no conflict. +--connection node_1 +COMMIT; + +DROP TABLE child, parent; + +--disconnect node_1a diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.test b/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.test new file mode 100644 index 00000000000..6307b629e2b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ddl_fk_no_conflict.test @@ -0,0 +1,57 @@ +# +# This test attempts to show that table admin commands +# (OPTIMIZE / REPAIR / ANALYZE ...) on child table, +# do NOT cause conflicts on parent table operations. +# Contrary to what is said in MDEV-21577, which claimed +# that OPTIMIZE and REPAIR do take MDL locks on parent +# table. +# +# Should this test start failing due to a conflict +# (i.e. ER_LOCK_DEADLOCK), then it might be that we +# are missing additional keys for certification +# on the corresponding table admin command. + +--source include/galera_cluster.inc + +--let $table_admin_command = OPTIMIZE +--let $fk_constraint = +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc + + +--let $table_admin_command = REPAIR +--let $fk_constraint = +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc + + +--let $table_admin_command = CHECK +--let $fk_constraint = +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc + + +--let $table_admin_command = ANALYZE +--let $fk_constraint = +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc +--let $fk_constraint = ON UPDATE CASCADE ON DELETE CASCADE +--source galera_ddl_fk_no_conflict.inc diff --git a/mysql-test/suite/galera/t/galera_repair_view.test b/mysql-test/suite/galera/t/galera_repair_view.test new file mode 100644 index 00000000000..0010d90c7ec --- /dev/null +++ b/mysql-test/suite/galera/t/galera_repair_view.test @@ -0,0 +1,12 @@ +--source include/galera_cluster.inc + +CREATE TABLE t1(a int not null primary key) engine=innodb; +REPAIR TABLE t1; +CREATE VIEW v1 AS SELECT a FROM t1; +REPAIR VIEW v1; +DROP VIEW v1; +DROP TABLE t1; + +CREATE VIEW v1 AS SELECT table_name FROM information_schema.tables; +REPAIR VIEW v1; +DROP VIEW v1; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index f692afb1440..213d77f8237 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -436,49 +436,6 @@ dbug_err: return open_error; } -#ifdef WITH_WSREP - /* - OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the affected table, but - also for the table referenced by foreign key constraint. - This wsrep_toi_replication() function handles TOI replication for OPTIMIZE and REPAIR - so that certification keys for potential FK parent tables are also appended in the - write set. - ALTER TABLE case is handled elsewhere. - */ -static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables) -{ - LEX *lex= thd->lex; - /* only handle OPTIMIZE and REPAIR here */ - switch (lex->sql_command) - { - case SQLCOM_OPTIMIZE: - case SQLCOM_REPAIR: - break; - default: - return false; - } - - close_thread_tables(thd); - wsrep::key_array keys; - - wsrep_append_fk_parent_table(thd, tables, &keys); - - /* now TOI replication, with no locks held */ - if (keys.empty()) - { - if (!thd->lex->no_write_to_binlog && - wsrep_to_isolation_begin(thd, NULL, NULL, tables)) - return true; - } - else - { - if (!thd->lex->no_write_to_binlog && - wsrep_to_isolation_begin(thd, NULL, NULL, tables, NULL, &keys)) - return true; - } - return false; -} -#endif /* WITH_WSREP */ /* RETURN VALUES @@ -550,16 +507,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, close_thread_tables(thd); for (table= tables; table; table= table->next_local) table->table= NULL; -#ifdef WITH_WSREP - if (WSREP(thd)) - { - if(wsrep_toi_replication(thd, tables)) - { - WSREP_INFO("wsrep TOI replication of has failed."); - goto err; - } - } -#endif /* WITH_WSREP */ for (table= tables; table; table= table->next_local) { @@ -1468,6 +1415,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); res= (specialflag & SPECIAL_NO_NEW_FUNC) ? mysql_recreate_table(thd, first_table, true) : mysql_admin_table(thd, first_table, &m_lex->check_opt, @@ -1477,6 +1425,9 @@ bool Sql_cmd_optimize_table::execute(THD *thd) m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; +#ifdef WITH_WSREP +wsrep_error_label: +#endif /* WITH_WSREP */ error: DBUG_RETURN(res); } @@ -1492,6 +1443,8 @@ bool Sql_cmd_repair_table::execute(THD *thd) if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ + + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair", TL_WRITE, 1, MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM), @@ -1501,6 +1454,9 @@ bool Sql_cmd_repair_table::execute(THD *thd) m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; +#ifdef WITH_WSREP +wsrep_error_label: +#endif /* WITH_WSREP */ error: DBUG_RETURN(res); } |