mirror of
https://github.com/MariaDB/server.git
synced 2025-12-06 05:42:06 +03:00
Adding a FK constraint to an existing table (ALTER TABLE ADD FOREIGN KEY) causes the applier to fail, if a concurrent DML statement that violate the new constraint (i.e. a DELETE or UPDATE of record in the parent table). For exmaple, the following scenario causes a crash in the applier: 1. ALTER successfully adds FK constraint in node_1 2. On node_2 is UPDATE is in pre_commit() and has certified successfully 3. ALTER is delivered in node_2 and BF aborts DML 4. Applying UPDATE event causes FK violation in node_1 To avoid this situation it is necessary for UPDATE to fail during certification. And for the UPDATE to fail certfication it is necessary that ALTER appends certification keys for both the child and the parent table. Before this patch, ALTER TABLE ADD FK only appended keys for child table which is ALTERed.
112 lines
3.6 KiB
Plaintext
112 lines
3.6 KiB
Plaintext
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
|
|
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER) ENGINE=INNODB;
|
|
INSERT INTO p VALUES (1, 0);
|
|
INSERT INTO p VALUES (2, 0);
|
|
INSERT INTO c VALUES (1, 1);
|
|
INSERT INTO c VALUES (2, 2);
|
|
SET AUTOCOMMIT=ON;
|
|
START TRANSACTION;
|
|
UPDATE p SET f1 = f1 + 100;
|
|
SET SESSION wsrep_sync_wait = 0;
|
|
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
|
ALTER TABLE c ADD FOREIGN KEY (p_id) REFERENCES p(f1);
|
|
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';
|
|
COMMIT;
|
|
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=';
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
SELECT * FROM p;
|
|
f1 f2
|
|
1 0
|
|
2 0
|
|
SELECT * FROM c;
|
|
f1 p_id
|
|
1 1
|
|
2 2
|
|
DROP TABLE c;
|
|
DROP TABLE p;
|
|
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, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;
|
|
INSERT INTO p1 VALUES (1, 0), (2, 0);
|
|
INSERT INTO p2 VALUES (1, 0), (2, 0);
|
|
INSERT INTO c VALUES (1, 1, 1);
|
|
INSERT INTO c VALUES (2, 2, 2);
|
|
SET AUTOCOMMIT=ON;
|
|
START TRANSACTION;
|
|
UPDATE p1 SET f1 = f1 + 100;
|
|
SET SESSION wsrep_sync_wait = 0;
|
|
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
|
ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1);
|
|
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';
|
|
COMMIT;
|
|
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=';
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
SELECT * FROM p1;
|
|
f1 f2
|
|
1 0
|
|
2 0
|
|
SELECT * FROM p2;
|
|
f1 f2
|
|
1 0
|
|
2 0
|
|
SELECT * FROM c;
|
|
f1 p_id1 p_id2
|
|
1 1 1
|
|
2 2 2
|
|
DROP TABLE c;
|
|
DROP TABLE p1;
|
|
DROP TABLE p2;
|
|
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, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;
|
|
INSERT INTO p1 VALUES (1, 0), (2, 0);
|
|
INSERT INTO p2 VALUES (1, 0), (2, 0);
|
|
INSERT INTO c VALUES (1, 1, 1);
|
|
INSERT INTO c VALUES (2, 2, 2);
|
|
SET AUTOCOMMIT=ON;
|
|
START TRANSACTION;
|
|
UPDATE p2 SET f1 = f1 + 100;
|
|
SET SESSION wsrep_sync_wait = 0;
|
|
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
|
ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1);
|
|
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';
|
|
COMMIT;
|
|
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=';
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
SELECT * FROM p1;
|
|
f1 f2
|
|
1 0
|
|
2 0
|
|
SELECT * FROM p2;
|
|
f1 f2
|
|
1 0
|
|
2 0
|
|
SELECT * FROM c;
|
|
f1 p_id1 p_id2
|
|
1 1 1
|
|
2 2 2
|
|
DROP TABLE c;
|
|
DROP TABLE p1;
|
|
DROP TABLE p2;
|