bound-corrupt-record-retries.patch
application/octet-stream
Filename: bound-corrupt-record-retries.patch
Type: application/octet-stream
Part: 0
Message:
Re: warning message in standby
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 34 | 6 |
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7165a3e..fd8520a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -488,6 +488,13 @@ static int readSource = 0; /* XLOG_FROM_* code */
* record from and failed.
*/
static int failedSources = 0;
+static int invalidRecordCount = 0;
+
+/*
+ * Number of times we're willing to find the same record invalid before
+ * deciding it is hopeless.
+ */
+#define MAX_INVALID_RECORD_COUNT 5
/* Buffer for currently read page (XLOG_BLCKSZ bytes) */
static char *readBuf = NULL;
@@ -577,6 +584,7 @@ static void ValidateXLOGDirectoryStructure(void);
static void CleanupBackupHistory(void);
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force);
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt);
+static void TallyInvalidRecord(int source);
static void CheckRecoveryConsistency(void);
static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt);
@@ -3691,6 +3699,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
/* This is the first try to read this page. */
failedSources = 0;
+ invalidRecordCount = 0;
retry:
/* Read the page containing the record */
if (!XLogPageRead(RecPtr, emode, fetching_ckpt, randAccess))
@@ -3924,7 +3933,7 @@ retry:
return (XLogRecord *) buffer;
next_record_is_invalid:
- failedSources |= readSource;
+ TallyInvalidRecord(readSource);
if (readFile >= 0)
{
@@ -3940,6 +3949,26 @@ next_record_is_invalid:
}
/*
+ * If we keep rereading the same WAL location and the record at that location
+ * keeps being invalid, abort recovery. Administrator intervention is
+ * required; continuing to reread the same data won't help. This will shut
+ * down Hot Standby if it's running, but a standby which is unrecoverably out
+ * of sync with the master is not what most people want.
+ */
+static void
+TallyInvalidRecord(int source)
+{
+ failedSources |= source;
+ if (source != XLOG_FROM_PG_XLOG)
+ {
+ if (++invalidRecordCount >= MAX_INVALID_RECORD_COUNT)
+ ereport(ERROR,
+ (errmsg("invalid record in WAL stream"),
+ errhint("Take a new base backup, or remove recovery.conf and restart in read-write mode.")));
+ }
+}
+
+/*
* Check whether the xlog header of a page just read in looks valid.
*
* This is just a convenience subroutine to avoid duplicated code in
@@ -9203,7 +9232,7 @@ StartupProcessMain(void)
* In standby mode, if after a successful return of XLogPageRead() the
* caller finds the record it's interested in to be broken, it should
* ereport the error with the level determined by
- * emode_for_corrupt_record(), and then set "failedSources |= readSource"
+ * emode_for_corrupt_record(), and then TallyInvalidRecord(readSource)
* and call XLogPageRead() again with the same arguments. This lets
* XLogPageRead() to try fetching the record from another source, or to
* sleep and retry.
@@ -9275,9 +9304,8 @@ retry:
/*
* If we find an invalid record in the WAL streamed from
* master, something is seriously wrong. There's little
- * chance that the problem will just go away, but PANIC
- * is not good for availability either, especially in
- * hot standby mode. Disconnect, and retry from
+ * chance that the problem will just go away, but we have
+ * to do something. Disconnect, and retry from
* archive/pg_xlog again. The WAL in the archive should
* be identical to what was streamed, so it's unlikely
* that it helps, but one can hope...
@@ -9513,7 +9541,7 @@ retry:
return true;
next_record_is_invalid:
- failedSources |= readSource;
+ TallyInvalidRecord(readSource);
if (readFile >= 0)
close(readFile);