mirror of https://github.com/citusdata/citus.git
Fix distributed deadlock for ALTER TABLE ... ATTACH PARTITION.
Following scenario resulted in distributed deadlock before this commit: CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time); CREATE TABLE partitioning_test_2009 (LIKE partitioning_test); CREATE TABLE partitioning_test_reference(id int PRIMARY KEY, subid int); SELECT create_distributed_table('partitioning_test_2009', 'id'), create_distributed_table('partitioning_test', 'id'), create_reference_table('partitioning_test_reference'); ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey FOREIGN KEY (id) REFERENCES partitioning_test_reference(id) ON DELETE CASCADE; ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009 FOREIGN KEY (id) REFERENCES partitioning_test_reference(id) ON DELETE CASCADE; ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');pull/2629/head
parent
f19feb742c
commit
cdd3b15ac8
|
@ -1198,7 +1198,7 @@ SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (alterTableType == AT_DetachPartition)
|
||||
else if (alterTableType == AT_DetachPartition || alterTableType == AT_AttachPartition)
|
||||
{
|
||||
/* check if there are foreign constraints to reference tables */
|
||||
if (HasForeignKeyToReferenceTable(relationId))
|
||||
|
|
|
@ -1882,6 +1882,80 @@ ORDER BY
|
|||
"schema-test_2009" | 4
|
||||
(2 rows)
|
||||
|
||||
-- test we don't deadlock when attaching and detaching partitions from partitioned
|
||||
-- tables with foreign keys
|
||||
CREATE TABLE reference_table(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE reference_table_2(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table_2');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
|
||||
CREATE TABLE partitioning_test_2008 PARTITION OF partitioning_test FOR VALUES FROM ('2008-01-01') TO ('2009-01-01');
|
||||
CREATE TABLE partitioning_test_2009 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2010 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2011 (LIKE partitioning_test);
|
||||
-- distributing partitioning_test will also distribute partitioning_test_2008
|
||||
SELECT create_distributed_table('partitioning_test', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2009', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2010', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2011', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01');
|
||||
-- This should fail because of foreign key constraint violation
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
ERROR: insert or update on table "partitioning_test_2010" violates foreign key constraint "partitioning_reference_fkey"
|
||||
DETAIL: Key (id)=(1) is not present in table "reference_table".
|
||||
-- Truncate, so attaching again won't fail
|
||||
TRUNCATE partitioning_test_2010;
|
||||
-- Attach a table which already has the same constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009
|
||||
FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
|
||||
-- Attach a table which doesn't have the constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
-- Attach a table which has a different constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2011
|
||||
FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2008;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2010;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011;
|
||||
DROP TABLE partitioning_test, partitioning_test_2008, partitioning_test_2009,
|
||||
partitioning_test_2010, partitioning_test_2011,
|
||||
reference_table, reference_table_2;
|
||||
DROP SCHEMA partitioning_schema CASCADE;
|
||||
NOTICE: drop cascades to table "schema-test"
|
||||
RESET SEARCH_PATH;
|
||||
|
|
|
@ -1806,6 +1806,82 @@ ORDER BY
|
|||
"schema-test_2009" | 4
|
||||
(2 rows)
|
||||
|
||||
-- test we don't deadlock when attaching and detaching partitions from partitioned
|
||||
-- tables with foreign keys
|
||||
CREATE TABLE reference_table(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE reference_table_2(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table_2');
|
||||
create_reference_table
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
|
||||
CREATE TABLE partitioning_test_2008 PARTITION OF partitioning_test FOR VALUES FROM ('2008-01-01') TO ('2009-01-01');
|
||||
CREATE TABLE partitioning_test_2009 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2010 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2011 (LIKE partitioning_test);
|
||||
-- distributing partitioning_test will also distribute partitioning_test_2008
|
||||
SELECT create_distributed_table('partitioning_test', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2009', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2010', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT create_distributed_table('partitioning_test_2011', 'id');
|
||||
create_distributed_table
|
||||
--------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
ERROR: foreign key constraints are not supported on partitioned tables
|
||||
LINE 1: ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_re...
|
||||
^
|
||||
ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01');
|
||||
-- This should fail because of foreign key constraint violation
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
-- Truncate, so attaching again won't fail
|
||||
TRUNCATE partitioning_test_2010;
|
||||
-- Attach a table which already has the same constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009
|
||||
FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
|
||||
-- Attach a table which doesn't have the constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
ERROR: "partitioning_test_2010" is already a partition
|
||||
-- Attach a table which has a different constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2011
|
||||
FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2008;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2010;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011;
|
||||
DROP TABLE partitioning_test, partitioning_test_2008, partitioning_test_2009,
|
||||
partitioning_test_2010, partitioning_test_2011,
|
||||
reference_table, reference_table_2;
|
||||
DROP SCHEMA partitioning_schema CASCADE;
|
||||
NOTICE: drop cascades to table "schema-test"
|
||||
RESET SEARCH_PATH;
|
||||
|
|
|
@ -1127,6 +1127,58 @@ GROUP BY
|
|||
ORDER BY
|
||||
1,2;
|
||||
|
||||
|
||||
-- test we don't deadlock when attaching and detaching partitions from partitioned
|
||||
-- tables with foreign keys
|
||||
CREATE TABLE reference_table(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table');
|
||||
|
||||
CREATE TABLE reference_table_2(id int PRIMARY KEY);
|
||||
SELECT create_reference_table('reference_table_2');
|
||||
|
||||
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
|
||||
CREATE TABLE partitioning_test_2008 PARTITION OF partitioning_test FOR VALUES FROM ('2008-01-01') TO ('2009-01-01');
|
||||
CREATE TABLE partitioning_test_2009 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2010 (LIKE partitioning_test);
|
||||
CREATE TABLE partitioning_test_2011 (LIKE partitioning_test);
|
||||
|
||||
-- distributing partitioning_test will also distribute partitioning_test_2008
|
||||
SELECT create_distributed_table('partitioning_test', 'id');
|
||||
SELECT create_distributed_table('partitioning_test_2009', 'id');
|
||||
SELECT create_distributed_table('partitioning_test_2010', 'id');
|
||||
SELECT create_distributed_table('partitioning_test_2011', 'id');
|
||||
|
||||
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009
|
||||
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01');
|
||||
-- This should fail because of foreign key constraint violation
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
-- Truncate, so attaching again won't fail
|
||||
TRUNCATE partitioning_test_2010;
|
||||
|
||||
-- Attach a table which already has the same constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009
|
||||
FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
|
||||
-- Attach a table which doesn't have the constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
|
||||
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||
-- Attach a table which has a different constraint
|
||||
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2011
|
||||
FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
|
||||
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2008;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2010;
|
||||
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011;
|
||||
|
||||
DROP TABLE partitioning_test, partitioning_test_2008, partitioning_test_2009,
|
||||
partitioning_test_2010, partitioning_test_2011,
|
||||
reference_table, reference_table_2;
|
||||
|
||||
DROP SCHEMA partitioning_schema CASCADE;
|
||||
RESET SEARCH_PATH;
|
||||
DROP TABLE IF EXISTS
|
||||
|
|
Loading…
Reference in New Issue