Re: Why standby restores some WALs many times from archive?

From: Sergey Burladyan <eshkinkot(at)gmail(dot)com>
To: Jeff Janes <jeff(dot)janes(at)gmail(dot)com>
Cc: Victor Yagofarov <xnasx(at)yandex(dot)ru>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Why standby restores some WALs many times from archive?
Date: 2018-01-10 19:07:14
Message-ID: 87shbd5y8t.fsf@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I think I found what happened here.

One WAL record can be split between WAL files.

In XLogReadRecord, if last WAL record is incomplete, it try to get next WAL:
/* Copy the first fragment of the record from the first page. */
memcpy(state->readRecordBuf,
state->readBuf + RecPtr % XLOG_BLCKSZ, len);
buffer = state->readRecordBuf + len;
gotlen = len;

do
{
/* Calculate pointer to beginning of next page */
targetPagePtr += XLOG_BLCKSZ;

/* Wait for the next page to become available */
readOff = ReadPageInternal(state, targetPagePtr,
Min(total_len - gotlen + SizeOfXLogShortPHD,
XLOG_BLCKSZ));

if (readOff < 0)
goto err;

but in my case next WAL not yet in archive (archive_timeout=0 in master)
and it clean cache:
err:

/*
* Invalidate the xlog page we've cached. We might read from a different
* source after failure.
*/
state->readSegNo = 0;
state->readOff = 0;
state->readLen = 0;

PG switch to streaming and last WAL (00000001000000000000002B for
example) still not replayed completely. We do not use streaming and it
switch back to archive:
LOG: restored log file "00000001000000000000002B" from archive
...
DEBUG: could not restore file "00000001000000000000002C" from archive: child process exited with exit code 1
DEBUG: switched WAL source from archive to stream after failure
DEBUG: switched WAL source from stream to archive after failure

Now it must reread first part of last WAL record from
00000001000000000000002B, but XLogFileReadAnyTLI is _always_ read
from the archive first, even if this file is already in pg_xlog:
if (source == XLOG_FROM_ANY || source == XLOG_FROM_ARCHIVE)
{
fd = XLogFileRead(segno, emode, tli,
XLOG_FROM_ARCHIVE, true);
if (fd != -1)
{
elog(DEBUG1, "got WAL segment from archive");
if (!expectedTLEs)
expectedTLEs = tles;
return fd;
}
}

if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_XLOG)
{
fd = XLogFileRead(segno, emode, tli,
XLOG_FROM_PG_XLOG, true);
if (fd != -1)
{
if (!expectedTLEs)
expectedTLEs = tles;
return fd;
}
}

Well, I think we'll be able to cache locally the last WAL file in restore_command
if needed :-)

--
Sergey Burladyan

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Eisentraut 2018-01-10 19:23:55 Re: portal pinning
Previous Message Shubham Barai 2018-01-10 18:55:57 Re: [HACKERS] GSoC 2017 : Patch for predicate locking in Gist index