> On 4 May 2017 at 20:05, Magnus Hagander <mag...@hagander.net> wrote: > > PFA a patch that adds a new function, pg_move_replication_slot, that makes it > possible to move the location of a replication slot without actually > consuming all the WAL on it.
Just a few questions just a few questions out of curiosity: * does it make sense to create a few tests for this function in `contrib/test_decoding` (as shown in attachment)? * what should happen if the second argument is `NULL`? There is a verification `XLogRecPtrIsInvalid(moveto)`, but it's possible to pass `NULL`, and looks like it leads to result different from boolean: ``` SELECT pg_move_replication_slot('regression_slot_5', NULL); pg_move_replication_slot -------------------------- (1 row) ```
diff --git a/contrib/test_decoding/expected/slot.out b/contrib/test_decoding/expected/slot.out index 9f5f8a9..7c69110 100644 --- a/contrib/test_decoding/expected/slot.out +++ b/contrib/test_decoding/expected/slot.out @@ -101,3 +101,39 @@ SELECT pg_drop_replication_slot('regression_slot1'); ERROR: replication slot "regression_slot1" does not exist SELECT pg_drop_replication_slot('regression_slot2'); ERROR: replication slot "regression_slot2" does not exist +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_3', 'test_decoding'); + ?column? +---------- + init +(1 row) + +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_4', 'test_decoding', true); + ?column? +---------- + init +(1 row) + +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_5', 'test_decoding'); + ?column? +---------- + init +(1 row) + +SELECT pg_move_replication_slot('regression_slot_3', '0/aabbccdd'); + pg_move_replication_slot +-------------------------- + t +(1 row) + +SELECT pg_move_replication_slot('regression_slot_4', '0/aabbccdd'); + pg_move_replication_slot +-------------------------- + t +(1 row) + +SELECT pg_move_replication_slot('regression_slot_5', NULL); + pg_move_replication_slot +-------------------------- + +(1 row) + diff --git a/contrib/test_decoding/sql/slot.sql b/contrib/test_decoding/sql/slot.sql index fa9561f..207f845 100644 --- a/contrib/test_decoding/sql/slot.sql +++ b/contrib/test_decoding/sql/slot.sql @@ -53,3 +53,12 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot1', 'test_ -- both should error as they should be dropped on error SELECT pg_drop_replication_slot('regression_slot1'); SELECT pg_drop_replication_slot('regression_slot2'); + +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_3', 'test_decoding'); +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_4', 'test_decoding', true); + +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_5', 'test_decoding'); + +SELECT pg_move_replication_slot('regression_slot_3', '0/aabbccdd'); +SELECT pg_move_replication_slot('regression_slot_4', '0/aabbccdd'); +SELECT pg_move_replication_slot('regression_slot_5', NULL); diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 6298657..d05974e 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -18986,6 +18986,24 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup()); be called when connected to the same database the slot was created on. </entry> </row> + <row> + <entry> + <indexterm> + <primary>pg_move_replication_slot</primary> + </indexterm> + <literal><function>pg_move_replication_slot(<parameter>slot_name</parameter> <type>name</type>, <parameter>position</parameter> <type>pg_lsn</type>)</function></literal> + </entry> + <entry> + <type>bool</type> + </entry> + <entry> + Moves the current restart position of a physical or logical + replication slot named <parameter>slot_name</parameter>. + The slot will not be moved backwards, and it will not be + moved beyond the current insert location. Returns true if + the position was changed. + </entry> + </row> <row> <entry> diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 6ee1e68..a9faa10 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -176,6 +176,66 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS) } /* + * SQL function for moving the position in a replication slot. + */ +Datum +pg_move_replication_slot(PG_FUNCTION_ARGS) +{ + Name slotname = PG_GETARG_NAME(0); + XLogRecPtr moveto = PG_GETARG_LSN(1); + char *slotnamestr; + bool changed = false; + bool backwards = false; + + Assert(!MyReplicationSlot); + + check_permissions(); + + if (XLogRecPtrIsInvalid(moveto)) + ereport(ERROR, + (errmsg("Invalid target xlog position "))); + + /* Temporarily acquire the slot so we "own" it */ + ReplicationSlotAcquire(NameStr(*slotname)); + + if (moveto > GetXLogWriteRecPtr()) + /* Can't move past current position, so truncate there */ + moveto = GetXLogWriteRecPtr(); + + /* Now adjust it */ + SpinLockAcquire(&MyReplicationSlot->mutex); + if (MyReplicationSlot->data.restart_lsn != moveto) + { + /* Never move backwards, because bad things can happen */ + if (MyReplicationSlot->data.restart_lsn > moveto) + backwards = true; + else + { + MyReplicationSlot->data.restart_lsn = moveto; + changed = true; + } + } + SpinLockRelease(&MyReplicationSlot->mutex); + + if (backwards) + ereport(WARNING, + (errmsg("Not moving replication slot backwards!"))); + + + if (changed) + { + ReplicationSlotMarkDirty(); + ReplicationSlotsComputeRequiredLSN(); + ReplicationSlotSave(); + } + + ReplicationSlotRelease(); + + PG_RETURN_BOOL(changed); +} + + +/* * pg_get_replication_slots - SQL SRF showing active replication slots. */ Datum diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 82562ad..04e97ff 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5289,6 +5289,8 @@ DATA(insert OID = 3779 ( pg_create_physical_replication_slot PGNSP PGUID 12 1 0 DESCR("create a physical replication slot"); DATA(insert OID = 3780 ( pg_drop_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f t f v u 1 0 2278 "19" _null_ _null_ _null_ _null_ _null_ pg_drop_replication_slot _null_ _null_ _null_ )); DESCR("drop a replication slot"); +DATA(insert OID = 3998 ( pg_move_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f t f v u 2 0 16 "19 3220" _null_ _null_ _null_ _null_ _null_ pg_move_replication_slot _null_ _null_ _null_ )); +DESCR("move a replication slot position"); DATA(insert OID = 3781 ( pg_get_replication_slots PGNSP PGUID 12 1 10 0 0 f f f f f t s s 0 0 2249 "" "{19,19,25,26,16,16,23,28,28,3220,3220}" "{o,o,o,o,o,o,o,o,o,o,o}" "{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn}" _null_ _null_ pg_get_replication_slots _null_ _null_ _null_ )); DESCR("information about replication slots currently in use"); DATA(insert OID = 3786 ( pg_create_logical_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f t f v u 3 0 2249 "19 19 16" "{19,19,16,25,3220}" "{i,i,i,o,o}" "{slot_name,plugin,temporary,slot_name,wal_position}" _null_ _null_ pg_create_logical_replication_slot _null_ _null_ _null_ ));
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers