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 */
|
/* check if there are foreign constraints to reference tables */
|
||||||
if (HasForeignKeyToReferenceTable(relationId))
|
if (HasForeignKeyToReferenceTable(relationId))
|
||||||
|
|
|
@ -1882,6 +1882,80 @@ ORDER BY
|
||||||
"schema-test_2009" | 4
|
"schema-test_2009" | 4
|
||||||
(2 rows)
|
(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;
|
DROP SCHEMA partitioning_schema CASCADE;
|
||||||
NOTICE: drop cascades to table "schema-test"
|
NOTICE: drop cascades to table "schema-test"
|
||||||
RESET SEARCH_PATH;
|
RESET SEARCH_PATH;
|
||||||
|
|
|
@ -1806,6 +1806,82 @@ ORDER BY
|
||||||
"schema-test_2009" | 4
|
"schema-test_2009" | 4
|
||||||
(2 rows)
|
(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;
|
DROP SCHEMA partitioning_schema CASCADE;
|
||||||
NOTICE: drop cascades to table "schema-test"
|
NOTICE: drop cascades to table "schema-test"
|
||||||
RESET SEARCH_PATH;
|
RESET SEARCH_PATH;
|
||||||
|
|
|
@ -1127,6 +1127,58 @@ GROUP BY
|
||||||
ORDER BY
|
ORDER BY
|
||||||
1,2;
|
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;
|
DROP SCHEMA partitioning_schema CASCADE;
|
||||||
RESET SEARCH_PATH;
|
RESET SEARCH_PATH;
|
||||||
DROP TABLE IF EXISTS
|
DROP TABLE IF EXISTS
|
||||||
|
|
Loading…
Reference in New Issue