log_recovery_conflict_waits_after_resolve.patch
text/plain
Filename: log_recovery_conflict_waits_after_resolve.patch
Type: text/plain
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 1 | 1 |
| src/backend/storage/buffer/bufmgr.c | 10 | 1 |
| src/backend/storage/ipc/standby.c | 36 | 11 |
| src/backend/storage/lmgr/proc.c | 11 | 1 |
| src/include/storage/standby.h | 2 | 1 |
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index e05f6eb732..1c02b6b042 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -6955,7 +6955,7 @@ log_line_prefix = '%m [%p] %q%u@%d/%a '
<listitem>
<para>
Controls whether a log message is produced when the startup process
- is waiting longer than <varname>deadlock_timeout</varname>
+ waits longer than <varname>deadlock_timeout</varname>
for recovery conflicts. This is useful in determining if recovery
conflicts prevent the recovery from applying WAL.
</para>
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 8499ea54f5..3442f0bc66 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3847,6 +3847,15 @@ LockBufferForCleanup(Buffer buffer)
/* Successfully acquired exclusive lock with pincount 1 */
UnlockBufHdr(bufHdr, buf_state);
+ /*
+ * Emit the log message if recovery conflict on buffer pin was resolved but
+ * the startup process waited longer than deadlock_timeout for it.
+ */
+ if (logged_recovery_conflict)
+ LogRecoveryConflict(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN,
+ waitStart, GetCurrentTimestamp(),
+ NULL, false);
+
/* Report change to non-waiting status */
if (new_status)
{
@@ -3901,7 +3910,7 @@ LockBufferForCleanup(Buffer buffer)
DeadlockTimeout))
{
LogRecoveryConflict(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN,
- waitStart, now, NULL);
+ waitStart, now, NULL, true);
logged_recovery_conflict = true;
}
}
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index cf4e630aa2..5db23c36d1 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -223,11 +223,14 @@ WaitExceedsMaxStandbyDelay(uint32 wait_event_info)
* wait_start is the timestamp when the caller started to wait.
* now is the timestamp when this function has been called.
* wait_list is the list of virtual transaction ids assigned to
- * conflicting processes.
+ * conflicting processes. still_waiting indicates whether
+ * the startup process is still waiting for the recovery conflict
+ * to be resolved or not.
*/
void
LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start,
- TimestampTz now, VirtualTransactionId *wait_list)
+ TimestampTz now, VirtualTransactionId *wait_list,
+ bool still_waiting)
{
long secs;
int usecs;
@@ -235,6 +238,12 @@ LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start,
StringInfoData buf;
int nprocs = 0;
+ /*
+ * There must be no conflicting processes when the recovery conflict has
+ * already been resolved.
+ */
+ Assert(still_waiting || wait_list == NULL);
+
TimestampDifference(wait_start, now, &secs, &usecs);
msecs = secs * 1000 + usecs / 1000;
usecs = usecs % 1000;
@@ -272,12 +281,21 @@ LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start,
* conflicting backends in a detail message. Note that if all the backends
* in the list are not active, no detail message is logged.
*/
- ereport(LOG,
- errmsg("recovery still waiting after %ld.%03d ms: %s",
- msecs, usecs, _(get_recovery_conflict_desc(reason))),
- nprocs > 0 ? errdetail_log_plural("Conflicting process: %s.",
- "Conflicting processes: %s.",
- nprocs, buf.data) : 0);
+ if (still_waiting)
+ {
+ ereport(LOG,
+ errmsg("recovery still waiting after %ld.%03d ms: %s",
+ msecs, usecs, _(get_recovery_conflict_desc(reason))),
+ nprocs > 0 ? errdetail_log_plural("Conflicting process: %s.",
+ "Conflicting processes: %s.",
+ nprocs, buf.data) : 0);
+ }
+ else
+ {
+ ereport(LOG,
+ errmsg("recovery finished waiting after %ld.%03d ms: %s",
+ msecs, usecs, _(get_recovery_conflict_desc(reason))));
+ }
if (nprocs > 0)
pfree(buf.data);
@@ -372,13 +390,12 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
/*
* Emit the log message if the startup process is waiting
- * longer than deadlock_timeout for recovery conflict on
- * buffer pin.
+ * longer than deadlock_timeout for recovery conflict.
*/
if (maybe_log_conflict &&
TimestampDifferenceExceeds(waitStart, now, DeadlockTimeout))
{
- LogRecoveryConflict(reason, waitStart, now, waitlist);
+ LogRecoveryConflict(reason, waitStart, now, waitlist, true);
logged_recovery_conflict = true;
}
}
@@ -388,6 +405,14 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
waitlist++;
}
+ /*
+ * Emit the log message if recovery conflict was resolved but the startup
+ * process waited longer than deadlock_timeout for it.
+ */
+ if (logged_recovery_conflict)
+ LogRecoveryConflict(reason, waitStart, GetCurrentTimestamp(),
+ NULL, false);
+
/* Reset ps display if we changed it */
if (new_status)
{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 527e38c974..8671c9dc10 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1327,7 +1327,8 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
* longer than deadlock_timeout.
*/
LogRecoveryConflict(PROCSIG_RECOVERY_CONFLICT_LOCK,
- standbyWaitStart, now, cnt > 0 ? vxids : NULL);
+ standbyWaitStart, now,
+ cnt > 0 ? vxids : NULL, true);
logged_recovery_conflict = true;
}
}
@@ -1612,6 +1613,15 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
disable_timeout(DEADLOCK_TIMEOUT, false);
}
+ /*
+ * Emit the log message if recovery conflict on lock was resolved
+ * but the startup process waited longer than deadlock_timeout for it.
+ */
+ if (logged_recovery_conflict && myWaitStatus == PROC_WAIT_STATUS_OK)
+ LogRecoveryConflict(PROCSIG_RECOVERY_CONFLICT_LOCK,
+ standbyWaitStart, GetCurrentTimestamp(),
+ NULL, false);
+
/*
* Re-acquire the lock table's partition lock. We have to do this to hold
* off cancel/die interrupts before we can mess with lockAwaited (else we
diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h
index 76ccd8cde4..17662f6fd7 100644
--- a/src/include/storage/standby.h
+++ b/src/include/storage/standby.h
@@ -40,7 +40,8 @@ extern void StandbyDeadLockHandler(void);
extern void StandbyTimeoutHandler(void);
extern void StandbyLockTimeoutHandler(void);
extern void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start,
- TimestampTz cur_ts, VirtualTransactionId *wait_list);
+ TimestampTz cur_ts, VirtualTransactionId *wait_list,
+ bool still_waiting);
/*
* Standby Rmgr (RM_STANDBY_ID)