fast_shutdown_syncrep_v1.patch
application/octet-stream
Filename: fast_shutdown_syncrep_v1.patch
Type: application/octet-stream
Part: 0
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 | + | − |
|---|---|---|
| src/backend/replication/syncrep.c | 44 | 0 |
| src/backend/tcop/dest.c | 22 | 0 |
| src/backend/tcop/postgres.c | 3 | 0 |
*** a/src/backend/replication/syncrep.c
--- b/src/backend/replication/syncrep.c
***************
*** 164,183 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
case SYNC_REP_WAITING:
/*
- * Check for conditions that would cause us to leave the
- * wait state before the LSN has been reached.
- */
- if (!PostmasterIsAlive(true))
- {
- LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
- SHMQueueDelete(&(MyProc->syncRepLinks));
- LWLockRelease(SyncRepLock);
-
- MyProc->syncRepState = SYNC_REP_MUST_DISCONNECT;
- return;
- }
-
- /*
* We don't receive SIGHUPs at this point, so resetting
* synchronous_standby_names has no effect on waiters.
*/
--- 164,169 ----
***************
*** 191,216 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
* WalSender has checked our LSN and has removed us from
* queue. Cleanup local state and leave.
*/
- Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
-
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
! MyProc->waitLSN.xlogid = 0;
! MyProc->waitLSN.xrecoff = 0;
!
! if (new_status)
! {
! /* Reset ps display */
! set_ps_display(new_status, false);
! pfree(new_status);
! }
!
! return;
case SYNC_REP_MUST_DISCONNECT:
return;
default:
! elog(FATAL, "invalid syncRepState");
}
/*
--- 177,212 ----
* WalSender has checked our LSN and has removed us from
* queue. Cleanup local state and leave.
*/
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
! goto cleanup;
case SYNC_REP_MUST_DISCONNECT:
return;
default:
! /*
! * Just close the connection without returning anything
! * to the client instead of throwing ERROR/FATAL error
! * since it's not allowed while in COMMIT state.
! */
! elog(WARNING, "invalid syncRepState");
! goto disconnect;
! }
!
! /*
! * Check for conditions that would cause us to leave the
! * wait state before the LSN has been reached.
! */
! if (!PostmasterIsAlive(true) || ProcDiePending)
! {
! if (ProcDiePending)
! ereport(LOG,
! (errcode(ERRCODE_ADMIN_SHUTDOWN),
! errmsg("canceling the wait for replication and terminating "
! "connection due to administrator command"),
! errdetail("The transaction has already been committed locally "
! "but might have not been replicated to the standby.")));
! goto disconnect;
}
/*
***************
*** 220,225 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
--- 216,241 ----
*/
WaitLatch(&MyProc->waitLatch, 60000000L);
}
+
+ disconnect:
+ LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
+ SHMQueueDelete(&(MyProc->syncRepLinks));
+ LWLockRelease(SyncRepLock);
+
+ MyProc->syncRepState = SYNC_REP_MUST_DISCONNECT;
+
+ cleanup:
+ Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
+
+ MyProc->waitLSN.xlogid = 0;
+ MyProc->waitLSN.xrecoff = 0;
+
+ if (new_status)
+ {
+ /* Reset ps display */
+ set_ps_display(new_status, false);
+ pfree(new_status);
+ }
}
/*
*** a/src/backend/tcop/dest.c
--- b/src/backend/tcop/dest.c
***************
*** 36,41 ****
--- 36,45 ----
#include "executor/tstoreReceiver.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
+ #include "miscadmin.h"
+ #include "replication/syncrep.h"
+ #include "storage/ipc.h"
+ #include "tcop/tcopprot.h"
#include "utils/portal.h"
***************
*** 144,149 **** EndCommand(const char *commandTag, CommandDest dest)
--- 148,171 ----
case DestRemoteExecute:
/*
+ * If we receive SIGTERM while we are waiting for synchronous
+ * replication, we close the connection before returning the
+ * "success" indication to the client. This prevents the client
+ * from thinking that the transaction which might have not been
+ * replicated yet has been committed and visible in the standby.
+ */
+ if (MyProc->syncRepState == SYNC_REP_MUST_DISCONNECT)
+ {
+ /*
+ * Reset whereToSendOutput to prevent ereport from
+ * attempting to send any more messages to client.
+ */
+ whereToSendOutput = DestNone;
+
+ proc_exit(0);
+ }
+
+ /*
* We assume the commandTag is plain ASCII and therefore requires
* no encoding conversion.
*/
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
***************
*** 2643,2648 **** die(SIGNAL_ARGS)
--- 2643,2651 ----
InterruptHoldoffCount--;
ProcessInterrupts();
}
+
+ /* Wake up myself waiting on the latch */
+ SetLatch(&(MyProc->waitLatch));
}
errno = save_errno;