Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ed46758

Browse filesBrowse files
committed
Logging running transactions every 15 seconds.
Previously, we did this just once per checkpoint, but that could make Hot Standby take a long time to initialize. To avoid busying an otherwise-idle system, we don't do this if no WAL has been written since we did it last. Andres Freund
1 parent d02c0dd commit ed46758
Copy full SHA for ed46758

File tree

Expand file treeCollapse file tree

3 files changed

+86
-5
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+86
-5
lines changed

‎src/backend/postmaster/bgwriter.c

Copy file name to clipboardExpand all lines: src/backend/postmaster/bgwriter.c
+62Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@
5454
#include "storage/shmem.h"
5555
#include "storage/smgr.h"
5656
#include "storage/spin.h"
57+
#include "storage/standby.h"
5758
#include "utils/guc.h"
5859
#include "utils/memutils.h"
5960
#include "utils/resowner.h"
61+
#include "utils/timestamp.h"
6062

6163

6264
/*
@@ -70,6 +72,20 @@ int BgWriterDelay = 200;
7072
*/
7173
#define HIBERNATE_FACTOR 50
7274

75+
/*
76+
* Interval in which standby snapshots are logged into the WAL stream, in
77+
* milliseconds.
78+
*/
79+
#define LOG_SNAPSHOT_INTERVAL_MS 15000
80+
81+
/*
82+
* LSN and timestamp at which we last issued a LogStandbySnapshot(), to avoid
83+
* doing so too often or repeatedly if there has been no other write activity
84+
* in the system.
85+
*/
86+
static TimestampTz last_snapshot_ts;
87+
static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr;
88+
7389
/*
7490
* Flags set by interrupt handlers for later service in the main loop.
7591
*/
@@ -141,6 +157,12 @@ BackgroundWriterMain(void)
141157
*/
142158
CurrentResourceOwner = ResourceOwnerCreate(NULL, "Background Writer");
143159

160+
/*
161+
* We just started, assume there has been either a shutdown or
162+
* end-of-recovery snapshot.
163+
*/
164+
last_snapshot_ts = GetCurrentTimestamp();
165+
144166
/*
145167
* Create a memory context that we will do all our work in. We do this so
146168
* that we can reset the context during error recovery and thereby avoid
@@ -275,6 +297,46 @@ BackgroundWriterMain(void)
275297
smgrcloseall();
276298
}
277299

300+
/*
301+
* Log a new xl_running_xacts every now and then so replication can get
302+
* into a consistent state faster (think of suboverflowed snapshots)
303+
* and clean up resources (locks, KnownXids*) more frequently. The
304+
* costs of this are relatively low, so doing it 4 times
305+
* (LOG_SNAPSHOT_INTERVAL_MS) a minute seems fine.
306+
*
307+
* We assume the interval for writing xl_running_xacts is
308+
* significantly bigger than BgWriterDelay, so we don't complicate the
309+
* overall timeout handling but just assume we're going to get called
310+
* often enough even if hibernation mode is active. It's not that
311+
* important that log_snap_interval_ms is met strictly. To make sure
312+
* we're not waking the disk up unneccesarily on an idle system we
313+
* check whether there has been any WAL inserted since the last time
314+
* we've logged a running xacts.
315+
*
316+
* We do this logging in the bgwriter as its the only process thats
317+
* run regularly and returns to its mainloop all the
318+
* time. E.g. Checkpointer, when active, is barely ever in its
319+
* mainloop and thus makes it hard to log regularly.
320+
*/
321+
if (XLogStandbyInfoActive() && !RecoveryInProgress())
322+
{
323+
TimestampTz timeout = 0;
324+
TimestampTz now = GetCurrentTimestamp();
325+
timeout = TimestampTzPlusMilliseconds(last_snapshot_ts,
326+
LOG_SNAPSHOT_INTERVAL_MS);
327+
328+
/*
329+
* only log if enough time has passed and some xlog record has been
330+
* inserted.
331+
*/
332+
if (now >= timeout &&
333+
last_snapshot_lsn != GetXLogInsertRecPtr())
334+
{
335+
last_snapshot_lsn = LogStandbySnapshot();
336+
last_snapshot_ts = now;
337+
}
338+
}
339+
278340
/*
279341
* Sleep until we are signaled or BgWriterDelay has elapsed.
280342
*

‎src/backend/storage/ipc/standby.c

Copy file name to clipboardExpand all lines: src/backend/storage/ipc/standby.c
+23-4Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlis
4242
ProcSignalReason reason);
4343
static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid);
4444
static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason);
45-
static void LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
45+
static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
4646
static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks);
4747

4848

@@ -853,10 +853,13 @@ standby_redo(XLogRecPtr lsn, XLogRecord *record)
853853
* currently running xids, performed by StandbyReleaseOldLocks().
854854
* Zero xids should no longer be possible, but we may be replaying WAL
855855
* from a time when they were possible.
856+
*
857+
* Returns the RecPtr of the last inserted record.
856858
*/
857-
void
859+
XLogRecPtr
858860
LogStandbySnapshot(void)
859861
{
862+
XLogRecPtr recptr;
860863
RunningTransactions running;
861864
xl_standby_lock *locks;
862865
int nlocks;
@@ -876,9 +879,12 @@ LogStandbySnapshot(void)
876879
* record we write, because standby will open up when it sees this.
877880
*/
878881
running = GetRunningTransactionData();
879-
LogCurrentRunningXacts(running);
882+
recptr = LogCurrentRunningXacts(running);
883+
880884
/* GetRunningTransactionData() acquired XidGenLock, we must release it */
881885
LWLockRelease(XidGenLock);
886+
887+
return recptr;
882888
}
883889

884890
/*
@@ -889,7 +895,7 @@ LogStandbySnapshot(void)
889895
* is a contiguous chunk of memory and never exists fully until it is
890896
* assembled in WAL.
891897
*/
892-
static void
898+
static XLogRecPtr
893899
LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
894900
{
895901
xl_running_xacts xlrec;
@@ -939,6 +945,19 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
939945
CurrRunningXacts->oldestRunningXid,
940946
CurrRunningXacts->latestCompletedXid,
941947
CurrRunningXacts->nextXid);
948+
949+
/*
950+
* Ensure running_xacts information is synced to disk not too far in the
951+
* future. We don't want to stall anything though (i.e. use XLogFlush()),
952+
* so we let the wal writer do it during normal
953+
* operation. XLogSetAsyncXactLSN() conveniently will mark the LSN as
954+
* to-be-synced and nudge the WALWriter into action if sleeping. Check
955+
* XLogBackgroundFlush() for details why a record might not be flushed
956+
* without it.
957+
*/
958+
XLogSetAsyncXactLSN(recptr);
959+
960+
return recptr;
942961
}
943962

944963
/*

‎src/include/storage/standby.h

Copy file name to clipboardExpand all lines: src/include/storage/standby.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,6 @@ typedef RunningTransactionsData *RunningTransactions;
113113
extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid);
114114
extern void LogAccessExclusiveLockPrepare(void);
115115

116-
extern void LogStandbySnapshot(void);
116+
extern XLogRecPtr LogStandbySnapshot(void);
117117

118118
#endif /* STANDBY_H */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.