Attached patch implements a "low watermark wal location" in the
walsender shmem array. Setting this value in a walsender prevents
transaction log removal prior to this point - similar to how
wal_keep_segments work, except with an absolute number rather than
relative. For now, this is set when running a base backup with WAL
included - to prevent the required WAL to be recycled away while the
backup is running, without having to guestimate the value for
wal_keep_segments. (There could be other ways added to set it in the
future, but that's the only one I've done for now)
It obviously needs some documentation updates as well, but I wanted to
get some comments on the way it's done before I work on those.
--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 8194,8199 **** CreateRestartPoint(int flags)
--- 8194,8206 ----
* Calculate the last segment that we need to retain because of
* wal_keep_segments, by subtracting wal_keep_segments from
* the given xlog location, recptr.
+ *
+ * Also check if there any in-progress base backup that has set
+ * a low watermark preventing us from removing it.
+ *
+ * NOTE! If the last segment calculated is later than the one
+ * passed in through logId and logSeg, do *not* update the
+ * values.
*/
static void
KeepLogSeg(XLogRecPtr recptr, uint32 *logId, uint32 *logSeg)
***************
*** 8202,8211 **** KeepLogSeg(XLogRecPtr recptr, uint32 *logId, uint32 *logSeg)
--- 8209,8260 ----
uint32 seg;
int d_log;
int d_seg;
+ XLogRecPtr lowwater = {0,0};
+ uint32 lowwater_log = 0;
+ uint32 lowwater_seg = 0;
+
+ if (max_wal_senders > 0)
+ {
+ int i;
+
+ /* Check if there is a WAL sender with a low watermark */
+ for (i = 0; i < max_wal_senders; i++)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
+ XLogRecPtr this_lowwater;
+
+ if (walsnd->pid == 0)
+ continue;
+
+ SpinLockAcquire(&walsnd->mutex);
+ this_lowwater = walsnd->lowwater;
+ SpinLockRelease(&walsnd->mutex);
+
+ if (XLByteLT(lowwater, this_lowwater))
+ lowwater = this_lowwater;
+ }
+
+ XLByteToSeg(lowwater, lowwater_log, lowwater_seg);
+ }
if (wal_keep_segments == 0)
+ {
+ /* No wal_keep_segments, so let low watermark decide */
+ if (lowwater_log == 0 && lowwater_seg == 0)
+ return;
+
+ if (lowwater_log < *logId || (lowwater_log == *logId && lowwater_seg < *logSeg))
+ {
+ *logId = lowwater_log;
+ *logSeg = lowwater_seg;
+ }
return;
+ }
+ /*
+ * Calculate the cutoff point caused by wal_keep_segments
+ */
XLByteToSeg(recptr, log, seg);
d_seg = wal_keep_segments % XLogSegsPerFile;
***************
*** 8226,8231 **** KeepLogSeg(XLogRecPtr recptr, uint32 *logId, uint32 *logSeg)
--- 8275,8293 ----
else
log = log - d_log;
+ /*
+ * If the low watermark is earlier than wal_keep_segments, let
+ * it decide if we keep or not.
+ */
+ if (lowwater_log > 0 || lowwater_seg > 0)
+ {
+ if (lowwater_log < log || (lowwater_log == log && lowwater_seg < seg))
+ {
+ log = lowwater_log;
+ seg = lowwater_seg;
+ }
+ }
+
/* don't delete WAL segments newer than the calculated segment */
if (log < *logId || (log == *logId && seg < *logSeg))
{
*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 96,101 **** perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
--- 96,115 ----
startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &labelfile);
SendXlogRecPtrResult(startptr);
+ /*
+ * If we are including WAL, set a low watermark so that ordinary
+ * WAL rotation won't remove the files for us.
+ */
+ if (opt->includewal)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile WalSnd *walsnd = MyWalSnd;
+
+ SpinLockAcquire(&walsnd->mutex);
+ walsnd->lowwater = startptr;
+ SpinLockRelease(&walsnd->mutex);
+ }
+
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
{
List *tablespaces = NIL;
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
***************
*** 899,904 **** InitWalSnd(void)
--- 899,905 ----
*/
walsnd->pid = MyProcPid;
MemSet(&walsnd->sentPtr, 0, sizeof(XLogRecPtr));
+ MemSet(&walsnd->lowwater, 0, sizeof(XLogRecPtr));
walsnd->state = WALSNDSTATE_STARTUP;
SpinLockRelease(&walsnd->mutex);
/* don't need the lock anymore */
*** a/src/include/replication/walsender.h
--- b/src/include/replication/walsender.h
***************
*** 46,51 **** typedef struct WalSnd
--- 46,57 ----
XLogRecPtr flush;
XLogRecPtr apply;
+ /*
+ * Prevent xlog rotation prior to the low watermark (used during base
+ * backups that include the transaction log)
+ */
+ XLogRecPtr lowwater;
+
/* Protects shared variables shown above. */
slock_t mutex;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers