16
16
-- List of nodes present in the cluster
17
17
CREATE TABLE nodes (
18
18
id serial PRIMARY KEY ,
19
+ super_connection_string text UNIQUE NOT NULL ,
19
20
connection_string text UNIQUE NOT NULL ,
20
21
replication_group text NOT NULL -- group of nodes within which shard replicas are allocated
21
22
);
@@ -45,8 +46,17 @@ CREATE TABLE replicas (
45
46
46
47
-- Shardman interface functions
47
48
48
- -- Add a node: adjust logical replication channels in replication group and create foreign servers
49
- CREATE FUNCTION add_node (conn_string text , repl_group text = ' all' ) RETURNS void AS $$
49
+ -- Add a node: adjust logical replication channels in replication group and
50
+ -- create foreign servers.
51
+ -- 'super_conn_string' is connection string to the node which allows to login to
52
+ -- the node as superuser, and 'conn_string' can be some other connstring.
53
+ -- The former is used for configuring logical replication, the latter for DDL
54
+ -- and for setting up FDW. This separation serves two purposes:
55
+ -- * It allows to access data without requiring superuser priviliges;
56
+ -- * It allows to set up pgbouncer, as replication can't go through it.
57
+ -- If conn_string is null, super_conn_string is used everywhere.
58
+ CREATE FUNCTION add_node (super_conn_string text , conn_string text = NULL ,
59
+ repl_group text = ' all' ) RETURNS void AS $$
50
60
DECLARE
51
61
new_node_id int ;
52
62
node shardman .nodes ;
@@ -71,14 +81,18 @@ DECLARE
71
81
fdw_part_name text ;
72
82
table_attrs text ;
73
83
srv_name text ;
84
+ conn_string_effective text = COALESCE(conn_string, super_conn_string);
74
85
BEGIN
75
- IF shardman .redirect_to_shardlord (format(' add_node(%L, %L)' , conn_string, repl_group))
86
+ IF shardman .redirect_to_shardlord (
87
+ format(' add_node(%L, %L, %L)' , super_conn_string, conn_string, repl_group))
76
88
THEN
77
89
RETURN;
78
90
END IF;
79
91
80
92
-- Insert new node in nodes table
81
- INSERT INTO shardman .nodes (connection_string,replication_group) VALUES (conn_string, repl_group) RETURNING id INTO new_node_id;
93
+ INSERT INTO shardman .nodes (super_connection_string, connection_string, replication_group)
94
+ VALUES (super_conn_string, conn_string_effective, repl_group)
95
+ RETURNING id INTO new_node_id;
82
96
83
97
-- Adjust replication channels within replication group.
84
98
-- We need all-to-all replication channels between all group members.
@@ -100,14 +114,14 @@ BEGIN
100
114
subs := format(' %s%s:CREATE SUBSCRIPTION sub_%s_%s CONNECTION %L PUBLICATION node_%s with (create_slot=false, slot_name=' ' node_%s' ' , synchronous_commit=local);
101
115
%s:CREATE SUBSCRIPTION sub_%s_%s CONNECTION %L PUBLICATION node_%s with (create_slot=false, slot_name=' ' node_%s' ' , synchronous_commit=local);' ,
102
116
subs,
103
- node .id , node .id , new_node_id, conn_string , node .id , node .id ,
104
- new_node_id, new_node_id, node .id , node .connection_string , new_node_id, new_node_id);
117
+ node .id , node .id , new_node_id, super_conn_string , node .id , node .id ,
118
+ new_node_id, new_node_id, node .id , node .super_connection_string , new_node_id, new_node_id);
105
119
END LOOP;
106
120
107
121
-- Broadcast create publication commands
108
- PERFORM shardman .broadcast (pubs);
122
+ PERFORM shardman .broadcast (pubs, super_connstr => true );
109
123
-- Broadcast create subscription commands
110
- PERFORM shardman .broadcast (subs);
124
+ PERFORM shardman .broadcast (subs, super_connstr => true );
111
125
112
126
-- In case of synchronous replication broadcast update synchronous standby list commands
113
127
IF shardman .synchronous_replication () AND
@@ -125,8 +139,8 @@ BEGIN
125
139
conf := format(' %s%s:SELECT pg_reload_conf();' , conf, node .id );
126
140
END LOOP;
127
141
128
- PERFORM shardman .broadcast (sync, sync_commit => true);
129
- PERFORM shardman .broadcast (conf);
142
+ PERFORM shardman .broadcast (sync, sync_commit_on => true, super_connstr => true);
143
+ PERFORM shardman .broadcast (conf, super_connstr => true );
130
144
END IF;
131
145
132
146
-- Add foreign servers for connection to the new node and backward
@@ -251,18 +265,20 @@ BEGIN
251
265
END LOOP;
252
266
253
267
-- Broadcast drop subscription commands, ignore errors because removed node may be not available
254
- PERFORM shardman .broadcast (subs, ignore_errors:= true, sync_commit => true);
268
+ PERFORM shardman .broadcast (subs, ignore_errors:= true, sync_commit_on => true,
269
+ super_connst => true);
255
270
-- Broadcast drop replication commands
256
- PERFORM shardman .broadcast (pubs, ignore_errors:= true);
271
+ PERFORM shardman .broadcast (pubs, ignore_errors:= true, super_connstr => true );
257
272
258
273
-- In case of synchronous replication update synchronous standbys list
259
274
IF shardman .synchronous_replication ()
260
275
THEN
261
276
-- On removed node, reset synchronous standbys list
262
277
sync := format(' %s%s:ALTER SYSTEM SET synchronous_standby_names to ' ' ' ' ;' ,
263
278
sync, rm_node_id, sync_standbys);
264
- PERFORM shardman .broadcast (sync, ignore_errors => true, sync_commit => true);
265
- PERFORM shardman .broadcast (conf, ignore_errors:= true);
279
+ PERFORM shardman .broadcast (sync, ignore_errors => true,
280
+ sync_commit_on => true, super_connstr => true);
281
+ PERFORM shardman .broadcast (conf, ignore_errors:= true, super_connstr => true);
266
282
END IF;
267
283
268
284
-- Remove foreign servers at all nodes for the removed node
@@ -305,9 +321,9 @@ BEGIN
305
321
END LOOP;
306
322
307
323
-- Broadcast alter publication commands
308
- PERFORM shardman .broadcast (pubs);
324
+ PERFORM shardman .broadcast (pubs, super_connstr => true );
309
325
-- Broadcast refresh alter subscription commands
310
- PERFORM shardman .broadcast (subs);
326
+ PERFORM shardman .broadcast (subs, super_connstr => true );
311
327
ELSE -- there is no replica: we have to create new empty partition at random mode and redirect all FDWs to it
312
328
SELECT id INTO new_master_id FROM shardman .nodes WHERE id<> rm_node_id ORDER BY random() LIMIT 1 ;
313
329
INSERT INTO shardman .partitions (part_name,node_id,relation) VALUES (part .part .name,new_master_id,part .relation );
@@ -478,15 +494,16 @@ BEGIN
478
494
END LOOP;
479
495
480
496
-- Broadcast alter publication commands
481
- PERFORM shardman .broadcast (pubs);
497
+ PERFORM shardman .broadcast (pubs, super_connstr => true );
482
498
-- Broadcast alter subscription commands
483
- PERFORM shardman .broadcast (subs, synchronous => copy_data);
499
+ PERFORM shardman .broadcast (subs, synchronous => copy_data, super_connstr => true );
484
500
485
501
-- This function doesn't wait completion of replication sync
486
502
END
487
503
$$ LANGUAGE plpgsql;
488
504
489
- -- Remove table from all nodes. All table partitions are removed.
505
+ -- Remove table from all nodes. All table partitions are removed, but replicas
506
+ -- and logical stuff not.
490
507
CREATE FUNCTION rm_table (rel regclass)
491
508
RETURNS void AS $$
492
509
DECLARE
@@ -547,7 +564,7 @@ BEGIN
547
564
END IF;
548
565
src_node_id := part .node_id ;
549
566
550
- SELECT replication_group,connection_string INTO src_repl_group,conn_string FROM shardman .nodes WHERE id= src_node_id;
567
+ SELECT replication_group, super_connection_string INTO src_repl_group, conn_string FROM shardman .nodes WHERE id= src_node_id;
551
568
SELECT replication_group INTO dst_repl_group FROM shardman .nodes WHERE id= dst_node_id;
552
569
553
570
IF src_node_id = dst_node_id THEN
@@ -576,8 +593,8 @@ BEGIN
576
593
dst_node_id, mv_part_name, conn_string, mv_part_name, mv_part_name);
577
594
578
595
-- Create publication and slot for copying
579
- PERFORM shardman .broadcast (pubs);
580
- PERFORM shardman .broadcast (subs);
596
+ PERFORM shardman .broadcast (pubs, super_connstr => true );
597
+ PERFORM shardman .broadcast (subs, super_connstr => true );
581
598
582
599
-- Wait completion of partition copy and prohibit access to this partition
583
600
PERFORM shardman .wait_copy_completion (src_node_id, mv_part_name);
@@ -603,12 +620,12 @@ BEGIN
603
620
END LOOP;
604
621
605
622
-- Broadcast alter publication commands
606
- PERFORM shardman .broadcast (pubs);
623
+ PERFORM shardman .broadcast (pubs, super_connstr => true );
607
624
-- Broadcast alter subscription commands
608
- PERFORM shardman .broadcast (subs);
625
+ PERFORM shardman .broadcast (subs, super_connstr => true );
609
626
-- Drop copy subscription
610
627
PERFORM shardman .broadcast (format(' %s:DROP SUBSCRIPTION copy_%s;' ,
611
- dst_node_id, mv_part_name), sync_commit: = true);
628
+ dst_node_id, mv_part_name), sync_commit_on => true, super_connstr => true);
612
629
613
630
-- Update owner of this partition
614
631
UPDATE shardman .partitions SET node_id= dst_node_id WHERE part_name= mv_part_name;
@@ -687,6 +704,7 @@ RETURNS text AS 'pg_shardman' LANGUAGE C STRICT;
687
704
-- prefix: node-id:sql-statement;
688
705
-- To run multiple statements on node, wrap them in {}:
689
706
-- {node-id:statement; statement;}
707
+ -- Node id '0' means shardlord, shardlord_connstring guc is used.
690
708
-- Don't specify them separately with 2pc, we use only one prepared_xact name.
691
709
-- No escaping is performed, so ';', '{' and '}' inside queries are not supported.
692
710
-- By default functions throws error is execution is failed at some of the
@@ -699,12 +717,15 @@ RETURNS text AS 'pg_shardman' LANGUAGE C STRICT;
699
717
-- If two_phase parameter is true, then each statement is wrapped in blocked and
700
718
-- prepared with subsequent commit or rollback of prepared transaction at second
701
719
-- phase of two phase commit.
702
- -- If sync_commit is false, we do set session synchronous_commit to local;
720
+ -- If sync_commit_on is false, we set session synchronous_commit to local.
721
+ -- If super_connstr is true, super connstring is used everywhere, usual
722
+ -- connstr otherwise.
703
723
CREATE FUNCTION broadcast (cmds text ,
704
724
ignore_errors bool = false,
705
725
two_phase bool = false,
706
- sync_commit bool = false,
707
- synchronous bool = false)
726
+ sync_commit_on bool = false,
727
+ synchronous bool = false,
728
+ super_connstr bool = false)
708
729
RETURNS text AS ' pg_shardman' LANGUAGE C STRICT;
709
730
710
731
-- Options to postgres_fdw are specified in two places: user & password in user
0 commit comments