mirror of https://github.com/citusdata/citus.git
Allow creating distributed tables in sequential mode
With https://github.com/citusdata/citus/pull/2780, we allow COPY to use any number of connections that the executor used in a tx block. Meaning that, while COPYing data to the shards, create_distributed_table could allow sequential mode.pull/5653/head
parent
8c8d696621
commit
b9b419ef16
|
@ -1539,19 +1539,7 @@ CanUseExclusiveConnections(Oid relationId, bool localTableEmpty)
|
||||||
bool shouldRunSequential = MultiShardConnectionType == SEQUENTIAL_CONNECTION ||
|
bool shouldRunSequential = MultiShardConnectionType == SEQUENTIAL_CONNECTION ||
|
||||||
hasForeignKeyToReferenceTable;
|
hasForeignKeyToReferenceTable;
|
||||||
|
|
||||||
if (!localTableEmpty && shouldRunSequential)
|
if (shouldRunSequential && ParallelQueryExecutedInTransaction())
|
||||||
{
|
|
||||||
char *relationName = get_rel_name(relationId);
|
|
||||||
|
|
||||||
ereport(ERROR, (errmsg("cannot distribute \"%s\" in sequential mode "
|
|
||||||
"because it is not empty", relationName),
|
|
||||||
errhint("If you have manually set "
|
|
||||||
"citus.multi_shard_modify_mode to 'sequential', "
|
|
||||||
"try with 'parallel' option. If that is not the "
|
|
||||||
"case, try distributing local tables when they "
|
|
||||||
"are empty.")));
|
|
||||||
}
|
|
||||||
else if (shouldRunSequential && ParallelQueryExecutedInTransaction())
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We decided to use sequential execution. It's either because relation
|
* We decided to use sequential execution. It's either because relation
|
||||||
|
|
|
@ -722,7 +722,7 @@ BEGIN;
|
||||||
|
|
||||||
UPDATE reference_table SET id = 101 WHERE id = 99;
|
UPDATE reference_table SET id = 101 WHERE id = 99;
|
||||||
ERROR: cannot modify table "reference_table" because there was a parallel operation on a distributed table
|
ERROR: cannot modify table "reference_table" because there was a parallel operation on a distributed table
|
||||||
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
||||||
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -734,7 +734,7 @@ BEGIN;
|
||||||
|
|
||||||
UPDATE transitive_reference_table SET id = 101 WHERE id = 99;
|
UPDATE transitive_reference_table SET id = 101 WHERE id = 99;
|
||||||
ERROR: cannot modify table "transitive_reference_table" because there was a parallel operation on a distributed table
|
ERROR: cannot modify table "transitive_reference_table" because there was a parallel operation on a distributed table
|
||||||
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
||||||
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- case 4.3: SELECT to a dist table is follwed by an unrelated DDL to a reference table
|
-- case 4.3: SELECT to a dist table is follwed by an unrelated DDL to a reference table
|
||||||
|
@ -1074,7 +1074,7 @@ BEGIN;
|
||||||
UPDATE unrelated_dist_table SET value_1 = 15;
|
UPDATE unrelated_dist_table SET value_1 = 15;
|
||||||
UPDATE reference_table SET id = 101 WHERE id = 99;
|
UPDATE reference_table SET id = 101 WHERE id = 99;
|
||||||
ERROR: cannot modify table "reference_table" because there was a parallel operation on a distributed table
|
ERROR: cannot modify table "reference_table" because there was a parallel operation on a distributed table
|
||||||
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
DETAIL: When there is a foreign key to a reference table or to a local table, Citus needs to perform all operations over a single connection per node to ensure consistency.
|
||||||
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
|
||||||
UPDATE on_update_fkey_table SET value_1 = 5 WHERE id != 11;
|
UPDATE on_update_fkey_table SET value_1 = 5 WHERE id != 11;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||||
|
@ -1282,8 +1282,8 @@ ERROR: current transaction is aborted, commands ignored until end of transactio
|
||||||
DROP TABLE test_table_1 CASCADE;
|
DROP TABLE test_table_1 CASCADE;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- make sure that we cannot create hash distributed tables with
|
-- make sure that we can create hash distributed tables with
|
||||||
-- foreign keys to reference tables when they have data in it
|
-- even when foreign keys to reference tables and they have data in it
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i;
|
||||||
|
@ -1300,16 +1300,21 @@ HINT: To remove the local data, run: SELECT truncate_local_data_after_distribut
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT create_distributed_table('test_table_2', 'id');
|
SELECT create_distributed_table('test_table_2', 'id');
|
||||||
ERROR: cannot distribute "test_table_2" in sequential mode because it is not empty
|
NOTICE: Copying data from local table...
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_fkey_to_ref_in_tx.test_table_2$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- make sure that the output isn't too verbose
|
-- make sure that the output isn't too verbose
|
||||||
SET LOCAL client_min_messages TO ERROR;
|
SET LOCAL client_min_messages TO ERROR;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
DROP TABLE test_table_2, test_table_1;
|
DROP TABLE test_table_2, test_table_1;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- the same test with above in sequential mode would still not work
|
-- the same test with above in sequential mode would just work
|
||||||
-- since COPY cannot be executed in sequential mode
|
-- as COPY can be executed in sequential mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
|
@ -1327,13 +1332,18 @@ HINT: To remove the local data, run: SELECT truncate_local_data_after_distribut
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT create_distributed_table('test_table_2', 'id');
|
SELECT create_distributed_table('test_table_2', 'id');
|
||||||
ERROR: cannot distribute "test_table_2" in sequential mode because it is not empty
|
NOTICE: Copying data from local table...
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_fkey_to_ref_in_tx.test_table_2$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- make sure that the output isn't too verbose
|
-- make sure that the output isn't too verbose
|
||||||
SET LOCAL client_min_messages TO ERROR;
|
SET LOCAL client_min_messages TO ERROR;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
DROP TABLE test_table_2, test_table_1;
|
DROP TABLE test_table_2, test_table_1;
|
||||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- we should be able to execute and DML/DDL/SELECT after we've
|
-- we should be able to execute and DML/DDL/SELECT after we've
|
||||||
-- switched to sequential via create_distributed_table
|
-- switched to sequential via create_distributed_table
|
||||||
|
|
|
@ -501,24 +501,23 @@ INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x;
|
||||||
SELECT truncate_local_data_after_distributing_table('ref');
|
SELECT truncate_local_data_after_distributing_table('ref');
|
||||||
ERROR: cannot truncate a table referenced in a foreign key constraint by a local table
|
ERROR: cannot truncate a table referenced in a foreign key constraint by a local table
|
||||||
DETAIL: Table "dist" references "ref"
|
DETAIL: Table "dist" references "ref"
|
||||||
-- test that we do not allow distributing tables that have foreign keys to reference tables
|
-- test that we allow distributing tables that have foreign keys to reference tables
|
||||||
SELECT create_distributed_table('dist','id');
|
SELECT create_distributed_table('dist','id');
|
||||||
ERROR: cannot distribute "dist" in sequential mode because it is not empty
|
NOTICE: Copying data from local table...
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$multi_truncate.dist$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SHOW citus.multi_shard_modify_mode;
|
SHOW citus.multi_shard_modify_mode;
|
||||||
citus.multi_shard_modify_mode
|
citus.multi_shard_modify_mode
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
parallel
|
parallel
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- distribute the table after a truncate
|
|
||||||
TRUNCATE dist;
|
|
||||||
SELECT create_distributed_table('dist','id');
|
|
||||||
create_distributed_table
|
|
||||||
---------------------------------------------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- the following should truncate ref and dist
|
-- the following should truncate ref and dist
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SELECT truncate_local_data_after_distributing_table('ref');
|
SELECT truncate_local_data_after_distributing_table('ref');
|
||||||
|
|
|
@ -610,20 +610,63 @@ SELECT distributed_2PCs_are_equal_to_worker_count();
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
DROP TABLE test_seq_ddl_index;
|
DROP TABLE test_seq_ddl_index;
|
||||||
-- create_distributed_table should fail on relations with data in sequential mode in and out transaction block
|
-- create_distributed_table should works on relations with data in sequential mode in and out transaction block
|
||||||
CREATE TABLE test_create_seq_table (a int);
|
CREATE TABLE test_create_seq_table (a int);
|
||||||
INSERT INTO test_create_seq_table VALUES (1);
|
INSERT INTO test_create_seq_table VALUES (1);
|
||||||
SET citus.multi_shard_modify_mode TO 'sequential';
|
SET citus.multi_shard_modify_mode TO 'sequential';
|
||||||
SELECT create_distributed_table('test_create_seq_table' ,'a');
|
SELECT create_distributed_table('test_create_seq_table' ,'a');
|
||||||
ERROR: cannot distribute "test_create_seq_table" in sequential mode because it is not empty
|
NOTICE: Copying data from local table...
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_seq_ddl.test_create_seq_table$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT undistribute_table('test_create_seq_table');
|
||||||
|
NOTICE: creating a new table for test_seq_ddl.test_create_seq_table
|
||||||
|
NOTICE: moving the data of test_seq_ddl.test_create_seq_table
|
||||||
|
NOTICE: dropping the old test_seq_ddl.test_create_seq_table
|
||||||
|
NOTICE: renaming the new table to test_seq_ddl.test_create_seq_table
|
||||||
|
undistribute_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
RESET citus.multi_shard_modify_mode;
|
RESET citus.multi_shard_modify_mode;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
select create_distributed_table('test_create_seq_table' ,'a');
|
select create_distributed_table('test_create_seq_table' ,'a');
|
||||||
ERROR: cannot distribute "test_create_seq_table" in sequential mode because it is not empty
|
NOTICE: Copying data from local table...
|
||||||
HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty.
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_seq_ddl.test_create_seq_table$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
-- trigger switch-over when using single connection per worker
|
||||||
|
BEGIN;
|
||||||
|
SET citus.next_shard_id TO 16900;
|
||||||
|
SET LOCAL citus.shard_count TO 4;
|
||||||
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
|
CREATE UNLOGGED TABLE trigger_switchover(a int, b int, c int, d int, e int, f int, g int, h int);
|
||||||
|
INSERT INTO trigger_switchover
|
||||||
|
SELECT s AS a, s AS b, s AS c, s AS d, s AS e, s AS f, s AS g, s AS h FROM generate_series(1,250000) s;
|
||||||
|
SELECT create_distributed_table('trigger_switchover','a');
|
||||||
|
NOTICE: Copying data from local table...
|
||||||
|
NOTICE: copying the data has completed
|
||||||
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
||||||
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_seq_ddl.trigger_switchover$$)
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ABORT;
|
||||||
SET search_path TO 'public';
|
SET search_path TO 'public';
|
||||||
DROP SCHEMA test_seq_ddl CASCADE;
|
DROP SCHEMA test_seq_ddl CASCADE;
|
||||||
NOTICE: drop cascades to 11 other objects
|
NOTICE: drop cascades to 11 other objects
|
||||||
|
|
|
@ -803,8 +803,8 @@ BEGIN;
|
||||||
DROP TABLE test_table_1 CASCADE;
|
DROP TABLE test_table_1 CASCADE;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
-- make sure that we cannot create hash distributed tables with
|
-- make sure that we can create hash distributed tables with
|
||||||
-- foreign keys to reference tables when they have data in it
|
-- even when foreign keys to reference tables and they have data in it
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
CREATE TABLE test_table_1(id int PRIMARY KEY);
|
||||||
|
@ -822,8 +822,8 @@ BEGIN;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
|
||||||
-- the same test with above in sequential mode would still not work
|
-- the same test with above in sequential mode would just work
|
||||||
-- since COPY cannot be executed in sequential mode
|
-- as COPY can be executed in sequential mode
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
|
|
|
@ -295,14 +295,10 @@ INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x;
|
||||||
-- test that we do not cascade truncates to local referencing tables
|
-- test that we do not cascade truncates to local referencing tables
|
||||||
SELECT truncate_local_data_after_distributing_table('ref');
|
SELECT truncate_local_data_after_distributing_table('ref');
|
||||||
|
|
||||||
-- test that we do not allow distributing tables that have foreign keys to reference tables
|
-- test that we allow distributing tables that have foreign keys to reference tables
|
||||||
SELECT create_distributed_table('dist','id');
|
SELECT create_distributed_table('dist','id');
|
||||||
SHOW citus.multi_shard_modify_mode;
|
SHOW citus.multi_shard_modify_mode;
|
||||||
|
|
||||||
-- distribute the table after a truncate
|
|
||||||
TRUNCATE dist;
|
|
||||||
SELECT create_distributed_table('dist','id');
|
|
||||||
|
|
||||||
-- the following should truncate ref and dist
|
-- the following should truncate ref and dist
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SELECT truncate_local_data_after_distributing_table('ref');
|
SELECT truncate_local_data_after_distributing_table('ref');
|
||||||
|
|
|
@ -326,12 +326,13 @@ COMMIT;
|
||||||
SELECT distributed_2PCs_are_equal_to_worker_count();
|
SELECT distributed_2PCs_are_equal_to_worker_count();
|
||||||
DROP TABLE test_seq_ddl_index;
|
DROP TABLE test_seq_ddl_index;
|
||||||
|
|
||||||
-- create_distributed_table should fail on relations with data in sequential mode in and out transaction block
|
-- create_distributed_table should works on relations with data in sequential mode in and out transaction block
|
||||||
CREATE TABLE test_create_seq_table (a int);
|
CREATE TABLE test_create_seq_table (a int);
|
||||||
INSERT INTO test_create_seq_table VALUES (1);
|
INSERT INTO test_create_seq_table VALUES (1);
|
||||||
|
|
||||||
SET citus.multi_shard_modify_mode TO 'sequential';
|
SET citus.multi_shard_modify_mode TO 'sequential';
|
||||||
SELECT create_distributed_table('test_create_seq_table' ,'a');
|
SELECT create_distributed_table('test_create_seq_table' ,'a');
|
||||||
|
SELECT undistribute_table('test_create_seq_table');
|
||||||
|
|
||||||
RESET citus.multi_shard_modify_mode;
|
RESET citus.multi_shard_modify_mode;
|
||||||
|
|
||||||
|
@ -340,5 +341,16 @@ BEGIN;
|
||||||
select create_distributed_table('test_create_seq_table' ,'a');
|
select create_distributed_table('test_create_seq_table' ,'a');
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
|
-- trigger switch-over when using single connection per worker
|
||||||
|
BEGIN;
|
||||||
|
SET citus.next_shard_id TO 16900;
|
||||||
|
SET LOCAL citus.shard_count TO 4;
|
||||||
|
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
|
||||||
|
CREATE UNLOGGED TABLE trigger_switchover(a int, b int, c int, d int, e int, f int, g int, h int);
|
||||||
|
INSERT INTO trigger_switchover
|
||||||
|
SELECT s AS a, s AS b, s AS c, s AS d, s AS e, s AS f, s AS g, s AS h FROM generate_series(1,250000) s;
|
||||||
|
SELECT create_distributed_table('trigger_switchover','a');
|
||||||
|
ABORT;
|
||||||
|
|
||||||
SET search_path TO 'public';
|
SET search_path TO 'public';
|
||||||
DROP SCHEMA test_seq_ddl CASCADE;
|
DROP SCHEMA test_seq_ddl CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue