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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers