Skip to content

Commit 77459eb

Browse files
committed
Bootstrap WAL to begin at segment logid=0 logseg=1 (000000010000000000000001)
rather than 0/0, so that we can safely use 0/0 as an invalid value. This is a more future-proof fix for the corner-case bug in streaming replication that was fixed yesterday. We had a similar corner-case bug with log/seg 0/0 back in February as well. Avoiding 0/0 as a valid value should prevent bugs like that in the future. Per Tom Lane's idea. Back-patch to 9.0. Since this only affects bootstrapping, it makes no difference to existing installations. We don't need to worry about the bug in existing installations, because if you've managed to get past the initial base backup already, you won't hit the bug in the future either.
1 parent 268fecc commit 77459eb

File tree

2 files changed

+13
-10
lines changed

2 files changed

+13
-10
lines changed

src/backend/access/transam/xlog.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ typedef struct XLogCtlData
363363
uint32 ckptXidEpoch; /* nextXID & epoch of latest checkpoint */
364364
TransactionId ckptXid;
365365
XLogRecPtr asyncXactLSN; /* LSN of newest async commit/abort */
366-
uint32 lastRemovedLog; /* latest removed/recycled XLOG segment + 1 */
366+
uint32 lastRemovedLog; /* latest removed/recycled XLOG segment */
367367
uint32 lastRemovedSeg;
368368

369369
/* Protected by WALWriteLock: */
@@ -3210,9 +3210,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
32103210
}
32113211

32123212
/*
3213-
* Get the log/seg of the first WAL segment that has not been removed or
3214-
* recycled. In other words, the log/seg of the last removed/recycled WAL
3215-
* segment + 1.
3213+
* Get the log/seg of the latest removed or recycled WAL segment.
32163214
* Returns 0/0 if no WAL segments have been removed since startup.
32173215
*/
32183216
void
@@ -3241,7 +3239,6 @@ UpdateLastRemovedPtr(char *filename)
32413239
seg;
32423240

32433241
XLogFromFileName(filename, &tli, &log, &seg);
3244-
NextLogSeg(log, seg);
32453242

32463243
SpinLockAcquire(&xlogctl->info_lck);
32473244
if (log > xlogctl->lastRemovedLog ||
@@ -4894,9 +4891,15 @@ BootStrapXLOG(void)
48944891
page = (XLogPageHeader) TYPEALIGN(ALIGNOF_XLOG_BUFFER, buffer);
48954892
memset(page, 0, XLOG_BLCKSZ);
48964893

4897-
/* Set up information for the initial checkpoint record */
4894+
/*
4895+
* Set up information for the initial checkpoint record
4896+
*
4897+
* The initial checkpoint record is written to the beginning of the
4898+
* WAL segment with logid=0 logseg=1. The very first WAL segment, 0/0, is
4899+
* not used, so that we can use 0/0 to mean "before any valid WAL segment".
4900+
*/
48984901
checkPoint.redo.xlogid = 0;
4899-
checkPoint.redo.xrecoff = SizeOfXLogLongPHD;
4902+
checkPoint.redo.xrecoff = XLogSegSize + SizeOfXLogLongPHD;
49004903
checkPoint.ThisTimeLineID = ThisTimeLineID;
49014904
checkPoint.nextXidEpoch = 0;
49024905
checkPoint.nextXid = FirstNormalTransactionId;
@@ -4919,7 +4922,7 @@ BootStrapXLOG(void)
49194922
page->xlp_info = XLP_LONG_HEADER;
49204923
page->xlp_tli = ThisTimeLineID;
49214924
page->xlp_pageaddr.xlogid = 0;
4922-
page->xlp_pageaddr.xrecoff = 0;
4925+
page->xlp_pageaddr.xrecoff = XLogSegSize;
49234926
longpage = (XLogLongPageHeader) page;
49244927
longpage->xlp_sysid = sysidentifier;
49254928
longpage->xlp_seg_size = XLogSegSize;
@@ -4945,7 +4948,7 @@ BootStrapXLOG(void)
49454948

49464949
/* Create first XLOG segment file */
49474950
use_existent = false;
4948-
openLogFile = XLogFileInit(0, 0, &use_existent, false);
4951+
openLogFile = XLogFileInit(0, 1, &use_existent, false);
49494952

49504953
/* Write the first page with the initial record */
49514954
errno = 0;

src/backend/replication/walsender.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ XLogRead(char *buf, XLogRecPtr recptr, Size nbytes)
630630
XLogGetLastRemoved(&lastRemovedLog, &lastRemovedSeg);
631631
XLByteToSeg(startRecPtr, log, seg);
632632
if (log < lastRemovedLog ||
633-
(log == lastRemovedLog && seg < lastRemovedSeg))
633+
(log == lastRemovedLog && seg <= lastRemovedSeg))
634634
{
635635
char filename[MAXFNAMELEN];
636636

0 commit comments

Comments
 (0)