Skip to content

Commit a924c32

Browse files
committed
Add support for temporary replication slots
This allows creating temporary replication slots that are removed automatically at the end of the session or on error. From: Petr Jelinek <[email protected]>
1 parent e7f051b commit a924c32

File tree

18 files changed

+237
-51
lines changed

18 files changed

+237
-51
lines changed

contrib/test_decoding/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ submake-test_decoding:
3939

4040
REGRESSCHECKS=ddl xact rewrite toast permissions decoding_in_xact \
4141
decoding_into_rel binary prepared replorigin time messages \
42-
spill
42+
spill slot
4343

4444
regresscheck: | submake-regress submake-test_decoding temp-install
4545
$(MKDIR_P) regression_output

contrib/test_decoding/expected/ddl.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ SELECT pg_drop_replication_slot('regression_slot');
702702

703703
/* check that the slot is gone */
704704
SELECT * FROM pg_replication_slots;
705-
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
706-
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
705+
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
706+
-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------
707707
(0 rows)
708708

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_p', 'test_decoding');
2+
?column?
3+
----------
4+
init
5+
(1 row)
6+
7+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_t', 'test_decoding', true);
8+
?column?
9+
----------
10+
init
11+
(1 row)
12+
13+
SELECT pg_drop_replication_slot('regression_slot_p');
14+
pg_drop_replication_slot
15+
--------------------------
16+
17+
(1 row)
18+
19+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_p', 'test_decoding', false);
20+
?column?
21+
----------
22+
init
23+
(1 row)
24+
25+
-- reconnect to clean temp slots
26+
\c
27+
SELECT pg_drop_replication_slot('regression_slot_p');
28+
pg_drop_replication_slot
29+
--------------------------
30+
31+
(1 row)
32+
33+
-- should fail because the temporary slot was dropped automatically
34+
SELECT pg_drop_replication_slot('regression_slot_t');
35+
ERROR: replication slot "regression_slot_t" does not exist
36+
-- test switching between slots in a session
37+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot1', 'test_decoding', true);
38+
?column?
39+
----------
40+
init
41+
(1 row)
42+
43+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot2', 'test_decoding', true);
44+
?column?
45+
----------
46+
init
47+
(1 row)
48+
49+
SELECT * FROM pg_logical_slot_get_changes('regression_slot1', NULL, NULL);
50+
location | xid | data
51+
----------+-----+------
52+
(0 rows)
53+
54+
SELECT * FROM pg_logical_slot_get_changes('regression_slot2', NULL, NULL);
55+
location | xid | data
56+
----------+-----+------
57+
(0 rows)
58+

contrib/test_decoding/sql/slot.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_p', 'test_decoding');
2+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_t', 'test_decoding', true);
3+
4+
SELECT pg_drop_replication_slot('regression_slot_p');
5+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_p', 'test_decoding', false);
6+
7+
-- reconnect to clean temp slots
8+
\c
9+
10+
SELECT pg_drop_replication_slot('regression_slot_p');
11+
12+
-- should fail because the temporary slot was dropped automatically
13+
SELECT pg_drop_replication_slot('regression_slot_t');
14+
15+
16+
-- test switching between slots in a session
17+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot1', 'test_decoding', true);
18+
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot2', 'test_decoding', true);
19+
SELECT * FROM pg_logical_slot_get_changes('regression_slot1', NULL, NULL);
20+
SELECT * FROM pg_logical_slot_get_changes('regression_slot2', NULL, NULL);

doc/src/sgml/func.sgml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18465,7 +18465,7 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1846518465
<indexterm>
1846618466
<primary>pg_create_physical_replication_slot</primary>
1846718467
</indexterm>
18468-
<literal><function>pg_create_physical_replication_slot(<parameter>slot_name</parameter> <type>name</type> <optional>, <parameter>immediately_reserve</> <type>boolean</> </optional>)</function></literal>
18468+
<literal><function>pg_create_physical_replication_slot(<parameter>slot_name</parameter> <type>name</type> <optional>, <parameter>immediately_reserve</> <type>boolean</>, <parameter>temporary</> <type>boolean</></optional>)</function></literal>
1846918469
</entry>
1847018470
<entry>
1847118471
(<parameter>slot_name</parameter> <type>name</type>, <parameter>xlog_position</parameter> <type>pg_lsn</type>)
@@ -18478,7 +18478,11 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1847818478
the <acronym>LSN</> is reserved on first connection from a streaming
1847918479
replication client. Streaming changes from a physical slot is only
1848018480
possible with the streaming-replication protocol &mdash;
18481-
see <xref linkend="protocol-replication">. This function corresponds
18481+
see <xref linkend="protocol-replication">. The optional third
18482+
parameter, <parameter>temporary</>, when set to true, specifies that
18483+
the slot should not be permanently stored to disk and is only meant
18484+
for use by current session. Temporary slots are also
18485+
released upon any error. This function corresponds
1848218486
to the replication protocol command <literal>CREATE_REPLICATION_SLOT
1848318487
... PHYSICAL</literal>.
1848418488
</entry>
@@ -18505,15 +18509,19 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
1850518509
<indexterm>
1850618510
<primary>pg_create_logical_replication_slot</primary>
1850718511
</indexterm>
18508-
<literal><function>pg_create_logical_replication_slot(<parameter>slot_name</parameter> <type>name</type>, <parameter>plugin</parameter> <type>name</type>)</function></literal>
18512+
<literal><function>pg_create_logical_replication_slot(<parameter>slot_name</parameter> <type>name</type>, <parameter>plugin</parameter> <type>name</type> <optional>, <parameter>temporary</> <type>boolean</></optional>)</function></literal>
1850918513
</entry>
1851018514
<entry>
1851118515
(<parameter>slot_name</parameter> <type>name</type>, <parameter>xlog_position</parameter> <type>pg_lsn</type>)
1851218516
</entry>
1851318517
<entry>
1851418518
Creates a new logical (decoding) replication slot named
1851518519
<parameter>slot_name</parameter> using the output plugin
18516-
<parameter>plugin</parameter>. A call to this function has the same
18520+
<parameter>plugin</parameter>. The optional third
18521+
parameter, <parameter>temporary</>, when set to true, specifies that
18522+
the slot should not be permanently stored to disk and is only meant
18523+
for use by current session. Temporary slots are also
18524+
released upon any error. A call to this function has the same
1851718525
effect as the replication protocol command
1851818526
<literal>CREATE_REPLICATION_SLOT ... LOGICAL</literal>.
1851918527
</entry>

doc/src/sgml/protocol.sgml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,7 @@ The commands accepted in walsender mode are:
14341434
</varlistentry>
14351435

14361436
<varlistentry>
1437-
<term><literal>CREATE_REPLICATION_SLOT</literal> <replaceable class="parameter">slot_name</> { <literal>PHYSICAL</> [ <literal>RESERVE_WAL</> ] | <literal>LOGICAL</> <replaceable class="parameter">output_plugin</> }
1437+
<term><literal>CREATE_REPLICATION_SLOT</literal> <replaceable class="parameter">slot_name</> [ <literal>TEMPORARY</> ] { <literal>PHYSICAL</> [ <literal>RESERVE_WAL</> ] | <literal>LOGICAL</> <replaceable class="parameter">output_plugin</> }
14381438
<indexterm><primary>CREATE_REPLICATION_SLOT</primary></indexterm>
14391439
</term>
14401440
<listitem>
@@ -1464,6 +1464,17 @@ The commands accepted in walsender mode are:
14641464
</listitem>
14651465
</varlistentry>
14661466

1467+
<varlistentry>
1468+
<term><literal>TEMPORARY</></term>
1469+
<listitem>
1470+
<para>
1471+
Specify that this replication slot is a temporary one. Temporary
1472+
slots are not saved to disk and are automatically dropped on error
1473+
or when the session has finished.
1474+
</para>
1475+
</listitem>
1476+
</varlistentry>
1477+
14671478
<varlistentry>
14681479
<term><literal>RESERVE_WAL</></term>
14691480
<listitem>

src/backend/catalog/system_views.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ CREATE VIEW pg_replication_slots AS
726726
L.slot_type,
727727
L.datoid,
728728
D.datname AS database,
729+
L.temporary,
729730
L.active,
730731
L.active_pid,
731732
L.xmin,
@@ -991,12 +992,22 @@ AS 'pg_logical_slot_peek_binary_changes';
991992

992993
CREATE OR REPLACE FUNCTION pg_create_physical_replication_slot(
993994
IN slot_name name, IN immediately_reserve boolean DEFAULT false,
995+
IN temporary boolean DEFAULT false,
994996
OUT slot_name name, OUT xlog_position pg_lsn)
995997
RETURNS RECORD
996998
LANGUAGE INTERNAL
997999
STRICT VOLATILE
9981000
AS 'pg_create_physical_replication_slot';
9991001

1002+
CREATE OR REPLACE FUNCTION pg_create_logical_replication_slot(
1003+
IN slot_name name, IN plugin name,
1004+
IN temporary boolean DEFAULT false,
1005+
OUT slot_name text, OUT xlog_position pg_lsn)
1006+
RETURNS RECORD
1007+
LANGUAGE INTERNAL
1008+
STRICT VOLATILE
1009+
AS 'pg_create_logical_replication_slot';
1010+
10001011
CREATE OR REPLACE FUNCTION
10011012
make_interval(years int4 DEFAULT 0, months int4 DEFAULT 0, weeks int4 DEFAULT 0,
10021013
days int4 DEFAULT 0, hours int4 DEFAULT 0, mins int4 DEFAULT 0,

src/backend/replication/repl_gram.y

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Node *replication_parse_result;
7777
%token K_LOGICAL
7878
%token K_SLOT
7979
%token K_RESERVE_WAL
80+
%token K_TEMPORARY
8081

8182
%type <node> command
8283
%type <node> base_backup start_replication start_logical_replication
@@ -89,7 +90,7 @@ Node *replication_parse_result;
8990
%type <defelt> plugin_opt_elem
9091
%type <node> plugin_opt_arg
9192
%type <str> opt_slot
92-
%type <boolval> opt_reserve_wal
93+
%type <boolval> opt_reserve_wal opt_temporary
9394

9495
%%
9596

@@ -183,24 +184,26 @@ base_backup_opt:
183184
;
184185

185186
create_replication_slot:
186-
/* CREATE_REPLICATION_SLOT slot PHYSICAL RESERVE_WAL */
187-
K_CREATE_REPLICATION_SLOT IDENT K_PHYSICAL opt_reserve_wal
187+
/* CREATE_REPLICATION_SLOT slot TEMPORARY PHYSICAL RESERVE_WAL */
188+
K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL opt_reserve_wal
188189
{
189190
CreateReplicationSlotCmd *cmd;
190191
cmd = makeNode(CreateReplicationSlotCmd);
191192
cmd->kind = REPLICATION_KIND_PHYSICAL;
192193
cmd->slotname = $2;
193-
cmd->reserve_wal = $4;
194+
cmd->temporary = $3;
195+
cmd->reserve_wal = $5;
194196
$$ = (Node *) cmd;
195197
}
196-
/* CREATE_REPLICATION_SLOT slot LOGICAL plugin */
197-
| K_CREATE_REPLICATION_SLOT IDENT K_LOGICAL IDENT
198+
/* CREATE_REPLICATION_SLOT slot TEMPORARY LOGICAL plugin */
199+
| K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT
198200
{
199201
CreateReplicationSlotCmd *cmd;
200202
cmd = makeNode(CreateReplicationSlotCmd);
201203
cmd->kind = REPLICATION_KIND_LOGICAL;
202204
cmd->slotname = $2;
203-
cmd->plugin = $4;
205+
cmd->temporary = $3;
206+
cmd->plugin = $5;
204207
$$ = (Node *) cmd;
205208
}
206209
;
@@ -276,6 +279,11 @@ opt_reserve_wal:
276279
| /* EMPTY */ { $$ = false; }
277280
;
278281

282+
opt_temporary:
283+
K_TEMPORARY { $$ = true; }
284+
| /* EMPTY */ { $$ = false; }
285+
;
286+
279287
opt_slot:
280288
K_SLOT IDENT
281289
{ $$ = $2; }

src/backend/replication/repl_scanner.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ PHYSICAL { return K_PHYSICAL; }
9898
RESERVE_WAL { return K_RESERVE_WAL; }
9999
LOGICAL { return K_LOGICAL; }
100100
SLOT { return K_SLOT; }
101+
TEMPORARY { return K_TEMPORARY; }
101102

102103
"," { return ','; }
103104
";" { return ';'; }

0 commit comments

Comments
 (0)