Commit ad432ef4 authored by sjaakola's avatar sjaakola Committed by Jan Lindström

MDEV-24119 MDL BF-BF Conflict caused by TRUNCATE TABLE

This PR fixes same issue as MDEV-21577 for TRUNCATE TABLE.
MDEV-21577 fixed TOI replication for OPTIMIZE, REPAIR and ALTER TABLE
operating on FK child table. It was later found out that also TRUNCATE
has similar problem and needs a fix.

The actual fix is to do FK parent table lookup before TRUNCATE TOI
isolation and append found FK parent table names in certification key
list for the write set.

PR contains also new test scenario in galera_ddl_fk_conflict test where
FK child has two FK parent tables and there are two DML transactions operating
on both parent tables.

For development convenience, new TO isolation macro was added:
WSREP_TO_ISOLATION_BEGIN_IF and WSREP_TO_ISOLATION_BEGIN_ALTER macro was changed
to skip the goto statement.
Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
parent 99a97747
......@@ -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__)
......
......@@ -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,63 @@ 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.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;
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.c optimize note Table does not support optimize, doing recreate + analyze instead
test.c optimize status OK
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 p SET f2 = 'TO DEADLOCK' WHERE pk = 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';
......@@ -67,15 +127,26 @@ 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';
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_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;
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,168 @@ 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 p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
connection node_2;
SET SESSION wsrep_sync_wait=0;
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_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;
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 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;
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 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;
TRUNCATE TABLE c1 ;
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 +470,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;
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 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 +485,67 @@ 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_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_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;
DROP TABLE c1, c2;
DROP TABLE p1, p2;
......@@ -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,62 @@ 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
--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';
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';
--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
......@@ -102,13 +166,19 @@ UPDATE p SET f2 = 'TO DEADLOCK' WHERE pk = 1;
--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_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;
DROP TABLE c1, c2;
DROP TABLE p1, p2;
......@@ -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
......@@ -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;
......
......@@ -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)
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment