mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Allow pg_create_physical_replication_slot() to reserve WAL.
When creating a physical slot it's often useful to immediately reserve the current WAL position instead of only doing after the first feedback message arrives. That e.g. allows slots to guarantee that all the WAL for a base backup will be available afterwards. Logical slots already have to reserve WAL during creation, so generalize that logic into being usable for both physical and logical slots. Catversion bump because of the new parameter. Author: Gurjeet Singh Reviewed-By: Andres Freund Discussion: CABwTF4Wh_dBCzTU=49pFXR6coR4NW1ynb+vBqT+Po=7fuq5iCw@mail.gmail.com
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "access/transam.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "common/string.h"
|
||||
#include "miscadmin.h"
|
||||
#include "replication/slot.h"
|
||||
@@ -781,6 +782,76 @@ CheckSlotRequirements(void)
|
||||
errmsg("replication slots can only be used if wal_level >= archive")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve WAL for the currently active slot.
|
||||
*
|
||||
* Compute and set restart_lsn in a manner that's appropriate for the type of
|
||||
* the slot and concurrency safe.
|
||||
*/
|
||||
void
|
||||
ReplicationSlotReserveWal(void)
|
||||
{
|
||||
ReplicationSlot *slot = MyReplicationSlot;
|
||||
|
||||
Assert(slot != NULL);
|
||||
Assert(slot->data.restart_lsn == InvalidXLogRecPtr);
|
||||
|
||||
/*
|
||||
* The replication slot mechanism is used to prevent removal of required
|
||||
* WAL. As there is no interlock between this routine and checkpoints, WAL
|
||||
* segments could concurrently be removed when a now stale return value of
|
||||
* ReplicationSlotsComputeRequiredLSN() is used. In the unlikely case that
|
||||
* this happens we'll just retry.
|
||||
*/
|
||||
while (true)
|
||||
{
|
||||
XLogSegNo segno;
|
||||
|
||||
/*
|
||||
* For logical slots log a standby snapshot and start logical decoding
|
||||
* at exactly that position. That allows the slot to start up more
|
||||
* quickly.
|
||||
*
|
||||
* That's not needed (or indeed helpful) for physical slots as they'll
|
||||
* start replay at the last logged checkpoint anyway. Instead return
|
||||
* the location of the last redo LSN. While that slightly increases
|
||||
* the chance that we have to retry, it's where a base backup has to
|
||||
* start replay at.
|
||||
*/
|
||||
if (!RecoveryInProgress() && SlotIsLogical(slot))
|
||||
{
|
||||
XLogRecPtr flushptr;
|
||||
|
||||
/* start at current insert position */
|
||||
slot->data.restart_lsn = GetXLogInsertRecPtr();
|
||||
|
||||
/* make sure we have enough information to start */
|
||||
flushptr = LogStandbySnapshot();
|
||||
|
||||
/* and make sure it's fsynced to disk */
|
||||
XLogFlush(flushptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->data.restart_lsn = GetRedoRecPtr();
|
||||
}
|
||||
|
||||
/* prevent WAL removal as fast as possible */
|
||||
ReplicationSlotsComputeRequiredLSN();
|
||||
|
||||
/*
|
||||
* If all required WAL is still there, great, otherwise retry. The
|
||||
* slot should prevent further removal of WAL, unless there's a
|
||||
* concurrent ReplicationSlotsComputeRequiredLSN() after we've written
|
||||
* the new restart_lsn above, so normally we should never need to loop
|
||||
* more than twice.
|
||||
*/
|
||||
XLByteToSeg(slot->data.restart_lsn, segno);
|
||||
if (XLogGetLastRemovedSegno() < segno)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush all replication slots to disk.
|
||||
*
|
||||
|
Reference in New Issue
Block a user