prevent_lock_conflict_from_slowing_failover_v1.patch
application/octet-stream
Filename: prevent_lock_conflict_from_slowing_failover_v1.patch
Type: application/octet-stream
Part: 0
Message:
Re: failover vs. read only queries
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: context
Series: patch v1
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 6 | 0 |
| doc/src/sgml/high-availability.sgml | 7 | 0 |
| src/backend/access/transam/xlog.c | 9 | 0 |
| src/backend/storage/ipc/standby.c | 16 | 0 |
| src/include/access/xlog.h | 3 | 0 |
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 1963,1968 **** SET ENABLE_SEQSCAN TO OFF;
--- 1963,1974 ----
allow significantly less than <varname>max_standby_delay</> seconds
before query cancellation is possible.
</para>
+ <para>
+ In standby mode, ever since the failover is requested, this parameter
+ is treated as zero, and all the conflicting queries are canceled
+ immediately. This is for preventing the conflict from slowing a recovery
+ and increasing the failover time.
+ </para>
</listitem>
</varlistentry>
*** a/doc/src/sgml/high-availability.sgml
--- b/doc/src/sgml/high-availability.sgml
***************
*** 1527,1532 **** if (!triggered)
--- 1527,1539 ----
heavy update load.
</para>
+ <para>
+ Note that, in standby mode, ever since the failover is requested,
+ <varname>max_standby_delay</> is treated as zero, and all the
+ conflicting queries are canceled immediately. This is for preventing
+ the conflict from slowing a recovery and increasing the failover time.
+ </para>
+
<caution>
<para>
Be sure that the primary and standby servers' clocks are kept in sync;
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 511,516 **** static bool InRedo = false;
--- 511,519 ----
/* Have we launched bgwriter during recovery? */
static bool bgwriterLaunched = false;
+ /* Have we found the trigger file? */
+ bool standbyIsTriggered = false;
+
/*
* Information logged when we detect a change in one of the parameters
* important for Hot Standby.
***************
*** 589,595 **** static void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
static void WriteControlFile(void);
static void ReadControlFile(void);
static char *str_time(pg_time_t tnow);
- static bool CheckForStandbyTrigger(void);
#ifdef WAL_DEBUG
static void xlog_outrec(StringInfo buf, XLogRecord *record);
--- 592,597 ----
***************
*** 9576,9582 **** emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
* to shut down walreceiver, wait for it to exit, remove the trigger
* file, and return true.
*/
! static bool
CheckForStandbyTrigger(void)
{
struct stat stat_buf;
--- 9578,9584 ----
* to shut down walreceiver, wait for it to exit, remove the trigger
* file, and return true.
*/
! bool
CheckForStandbyTrigger(void)
{
struct stat stat_buf;
***************
*** 9584,9595 **** CheckForStandbyTrigger(void)
--- 9586,9602 ----
if (TriggerFile == NULL)
return false;
+ /* Quick exit if already known triggered */
+ if (standbyIsTriggered)
+ return true;
+
if (stat(TriggerFile, &stat_buf) == 0)
{
ereport(LOG,
(errmsg("trigger file found: %s", TriggerFile)));
ShutdownWalRcv();
unlink(TriggerFile);
+ standbyIsTriggered = true;
return true;
}
return false;
*** a/src/backend/storage/ipc/standby.c
--- b/src/backend/storage/ipc/standby.c
***************
*** 124,133 **** static int standbyWait_us = STANDBY_INITIAL_WAIT_US;
static bool
WaitExceedsMaxStandbyDelay(void)
{
! /* Are we past max_standby_delay? */
! if (MaxStandbyDelay >= 0 &&
! TimestampDifferenceExceeds(GetLatestXLogTime(), GetCurrentTimestamp(),
! MaxStandbyDelay))
return true;
/*
--- 124,141 ----
static bool
WaitExceedsMaxStandbyDelay(void)
{
! /*
! * Are we past max_standby_delay?
! *
! * If we've already been triggered, we cancel all the conflicting queries
! * immediately to cause the recovery to end as soon as possible. Otherwise,
! * the lock contention between a recovery and queries might increase the
! * failover time significantly.
! */
! if (standbyIsTriggered || MaxStandbyDelay == 0 ||
! (MaxStandbyDelay > 0 &&
! TimestampDifferenceExceeds(GetLatestXLogTime(), GetCurrentTimestamp(),
! MaxStandbyDelay)))
return true;
/*
***************
*** 141,147 **** WaitExceedsMaxStandbyDelay(void)
--- 149,159 ----
*/
standbyWait_us *= 2;
if (standbyWait_us > 1000000)
+ {
standbyWait_us = 1000000;
+ if (CheckForStandbyTrigger())
+ return true;
+ }
return false;
}
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 196,201 **** extern bool EnableHotStandby;
--- 196,203 ----
extern int MaxStandbyDelay;
extern bool log_checkpoints;
+ extern bool standbyIsTriggered;
+
/* WAL levels */
typedef enum WalLevel
{
***************
*** 297,302 **** extern XLogRecPtr GetInsertRecPtr(void);
--- 299,305 ----
extern XLogRecPtr GetWriteRecPtr(void);
extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch);
extern TimeLineID GetRecoveryTargetTLI(void);
+ extern bool CheckForStandbyTrigger(void);
extern void HandleStartupProcInterrupts(void);
extern void StartupProcessMain(void);