static HTAB *RecoveryLockLists;
 
 static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
-                                      ProcSignalReason reason);
+                                      ProcSignalReason reason, bool report_waiting);
 static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid);
 static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason);
 static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
  * recovery processing. Judgement has already been passed on it within
  * a specific rmgr. Here we just issue the orders to the procs. The procs
  * then throw the required error as instructed.
+ *
+ * If report_waiting is true, "waiting" is reported in PS display if necessary.
+ * If the caller has already reported that, report_waiting should be false.
+ * Otherwise, "waiting" is reported twice unexpectedly.
  */
 static void
 ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
-                                      ProcSignalReason reason)
+                                      ProcSignalReason reason, bool report_waiting)
 {
-   TimestampTz waitStart;
+   TimestampTz waitStart = 0;
    char       *new_status;
 
    /* Fast exit, to avoid a kernel call if there's no work to be done. */
    if (!VirtualTransactionIdIsValid(*waitlist))
        return;
 
-   waitStart = GetCurrentTimestamp();
+   if (report_waiting)
+       waitStart = GetCurrentTimestamp();
    new_status = NULL;          /* we haven't changed the ps display */
 
    while (VirtualTransactionIdIsValid(*waitlist))
             * Report via ps if we have been waiting for more than 500 msec
             * (should that be configurable?)
             */
-           if (update_process_title && new_status == NULL &&
+           if (update_process_title && new_status == NULL && report_waiting &&
                TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(),
                                           500))
            {
                                         node.dbNode);
 
    ResolveRecoveryConflictWithVirtualXIDs(backends,
-                                        PROCSIG_RECOVERY_CONFLICT_SNAPSHOT);
+                                        PROCSIG_RECOVERY_CONFLICT_SNAPSHOT,
+                                        true);
 }
 
 void
    temp_file_users = GetConflictingVirtualXIDs(InvalidTransactionId,
                                                InvalidOid);
    ResolveRecoveryConflictWithVirtualXIDs(temp_file_users,
-                                      PROCSIG_RECOVERY_CONFLICT_TABLESPACE);
+                                      PROCSIG_RECOVERY_CONFLICT_TABLESPACE,
+                                      true);
 }
 
 void
                                                 InvalidOid);
 
        ResolveRecoveryConflictWithVirtualXIDs(backends,
-                                            PROCSIG_RECOVERY_CONFLICT_LOCK);
+                                            PROCSIG_RECOVERY_CONFLICT_LOCK,
+                                            false);
 
        if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true,
                                false, NULL) != LOCKACQUIRE_NOT_AVAIL)