2011-03-07 00:39:14 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* syncrep.c
|
|
|
|
*
|
|
|
|
* Synchronous replication is new as of PostgreSQL 9.1.
|
|
|
|
*
|
|
|
|
* If requested, transaction commits wait until their commit LSN is
|
2014-12-12 12:39:36 +01:00
|
|
|
* acknowledged by the synchronous standby.
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
|
|
|
* This module contains the code for waiting and release of backends.
|
|
|
|
* All code in this module executes on the primary. The core streaming
|
|
|
|
* replication transport remains within WALreceiver/WALsender modules.
|
|
|
|
*
|
|
|
|
* The essence of this design is that it isolates all logic about
|
|
|
|
* waiting/releasing onto the primary. The primary defines which standbys
|
|
|
|
* it wishes to wait for. The standby is completely unaware of the
|
|
|
|
* durability requirements of transactions on the primary, reducing the
|
|
|
|
* complexity of the code and streamlining both standby operations and
|
|
|
|
* network bandwidth because there is no requirement to ship
|
|
|
|
* per-transaction state information.
|
|
|
|
*
|
|
|
|
* Replication is either synchronous or not synchronous (async). If it is
|
2012-01-24 21:22:37 +01:00
|
|
|
* async, we just fastpath out of here. If it is sync, then we wait for
|
2013-09-03 12:17:09 +02:00
|
|
|
* the write or flush location on the standby before releasing the waiting
|
|
|
|
* backend. Further complexity in that interaction is expected in later
|
|
|
|
* releases.
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
|
|
|
* The best performing way to manage the waiting backends is to have a
|
|
|
|
* single ordered queue of waiting backends, so that we can avoid
|
|
|
|
* searching the through all waiters each time we receive a reply.
|
|
|
|
*
|
|
|
|
* In 9.1 we support only a single synchronous standby, chosen from a
|
|
|
|
* priority list of synchronous_standby_names. Before it can become the
|
|
|
|
* synchronous standby it must have caught up with the primary; that may
|
|
|
|
* take some time. Once caught up, the current highest priority standby
|
|
|
|
* will release waiters from the queue.
|
|
|
|
*
|
2015-01-06 17:43:47 +01:00
|
|
|
* Portions Copyright (c) 2010-2015, PostgreSQL Global Development Group
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2011-03-10 07:05:33 +01:00
|
|
|
* src/backend/replication/syncrep.c
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "access/xact.h"
|
|
|
|
#include "miscadmin.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "replication/syncrep.h"
|
|
|
|
#include "replication/walsender.h"
|
2011-09-12 20:24:29 +02:00
|
|
|
#include "replication/walsender_private.h"
|
2011-03-07 00:39:14 +01:00
|
|
|
#include "storage/pmsignal.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "storage/proc.h"
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
#include "tcop/tcopprot.h"
|
2011-03-07 00:39:14 +01:00
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/ps_status.h"
|
|
|
|
|
|
|
|
/* User-settable parameters for sync rep */
|
2011-04-10 17:42:00 +02:00
|
|
|
char *SyncRepStandbyNames;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
#define SyncStandbysDefined() \
|
|
|
|
(SyncRepStandbyNames != NULL && SyncRepStandbyNames[0] != '\0')
|
|
|
|
|
2011-03-07 00:39:14 +01:00
|
|
|
static bool announce_next_takeover = true;
|
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
static int SyncRepWaitMode = SYNC_REP_NO_WAIT;
|
|
|
|
|
|
|
|
static void SyncRepQueueInsert(int mode);
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
static void SyncRepCancelWait(void);
|
2015-03-26 02:34:08 +01:00
|
|
|
static int SyncRepWakeQueue(bool all, int mode);
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2011-04-10 17:42:00 +02:00
|
|
|
static int SyncRepGetStandbyPriority(void);
|
|
|
|
|
2011-03-07 08:56:53 +01:00
|
|
|
#ifdef USE_ASSERT_CHECKING
|
2012-01-24 21:22:37 +01:00
|
|
|
static bool SyncRepQueueIsOrderedByLSN(int mode);
|
2011-03-07 08:56:53 +01:00
|
|
|
#endif
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ===========================================================
|
|
|
|
* Synchronous Replication functions for normal user backends
|
|
|
|
* ===========================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for synchronous replication, if requested by user.
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
*
|
|
|
|
* Initially backends start in state SYNC_REP_NOT_WAITING and then
|
|
|
|
* change that state to SYNC_REP_WAITING before adding ourselves
|
|
|
|
* to the wait queue. During SyncRepWakeQueue() a WALSender changes
|
|
|
|
* the state to SYNC_REP_WAIT_COMPLETE once replication is confirmed.
|
|
|
|
* This backend then resets its state to SYNC_REP_NOT_WAITING.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
|
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
char *new_status = NULL;
|
2011-03-07 00:39:14 +01:00
|
|
|
const char *old_status;
|
2012-01-30 15:36:17 +01:00
|
|
|
int mode = SyncRepWaitMode;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Fast exit if user has not requested sync replication, or there are no
|
|
|
|
* sync replication standby names defined. Note that those standbys don't
|
|
|
|
* need to be connected.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
if (!SyncRepRequested() || !SyncStandbysDefined())
|
2011-03-07 00:39:14 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
Assert(WalSndCtl != NULL);
|
|
|
|
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
|
|
|
Assert(MyProc->syncRepState == SYNC_REP_NOT_WAITING);
|
2011-03-26 11:09:37 +01:00
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* We don't wait for sync rep if WalSndCtl->sync_standbys_defined is not
|
|
|
|
* set. See SyncRepUpdateSyncStandbysDefined.
|
2011-03-26 11:09:37 +01:00
|
|
|
*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Also check that the standby hasn't already replied. Unlikely race
|
2014-05-06 18:12:18 +02:00
|
|
|
* condition but we'll be fetching that cache line anyway so it's likely
|
|
|
|
* to be a low cost check.
|
2011-03-26 11:09:37 +01:00
|
|
|
*/
|
|
|
|
if (!WalSndCtl->sync_standbys_defined ||
|
2012-12-28 17:06:15 +01:00
|
|
|
XactCommitLSN <= WalSndCtl->lsn[mode])
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
{
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
return;
|
|
|
|
}
|
2011-03-26 11:09:37 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set our waitLSN so WALSender will know when to wake us, and add
|
|
|
|
* ourselves to the queue.
|
|
|
|
*/
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
MyProc->waitLSN = XactCommitLSN;
|
|
|
|
MyProc->syncRepState = SYNC_REP_WAITING;
|
2012-01-30 15:36:17 +01:00
|
|
|
SyncRepQueueInsert(mode);
|
|
|
|
Assert(SyncRepQueueIsOrderedByLSN(mode));
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
|
|
|
|
/* Alter ps display to show waiting for sync rep. */
|
|
|
|
if (update_process_title)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
old_status = get_ps_display(&len);
|
|
|
|
new_status = (char *) palloc(len + 32 + 1);
|
|
|
|
memcpy(new_status, old_status, len);
|
|
|
|
sprintf(new_status + len, " waiting for %X/%X",
|
2012-06-24 17:51:37 +02:00
|
|
|
(uint32) (XactCommitLSN >> 32), (uint32) XactCommitLSN);
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
set_ps_display(new_status, false);
|
|
|
|
new_status[len] = '\0'; /* truncate off " waiting ..." */
|
|
|
|
}
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for specified LSN to be confirmed.
|
|
|
|
*
|
|
|
|
* Each proc has its own wait latch, so we perform a normal latch
|
|
|
|
* check/wait loop here.
|
|
|
|
*/
|
|
|
|
for (;;)
|
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
int syncRepState;
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
|
|
|
|
/* Must reset the latch before testing state. */
|
2015-01-14 18:45:22 +01:00
|
|
|
ResetLatch(MyLatch);
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Try checking the state without the lock first. There's no
|
|
|
|
* guarantee that we'll read the most up-to-date value, so if it looks
|
|
|
|
* like we're still waiting, recheck while holding the lock. But if
|
|
|
|
* it looks like we're done, we must really be done, because once
|
|
|
|
* walsender changes the state to SYNC_REP_WAIT_COMPLETE, it will
|
|
|
|
* never update it again, so we can't be seeing a stale value in that
|
|
|
|
* case.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
syncRepState = MyProc->syncRepState;
|
|
|
|
if (syncRepState == SYNC_REP_WAITING)
|
|
|
|
syncRepState = MyProc->syncRepState;
|
|
|
|
if (syncRepState == SYNC_REP_WAIT_COMPLETE)
|
|
|
|
break;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
* If a wait for synchronous replication is pending, we can neither
|
2011-04-10 17:42:00 +02:00
|
|
|
* acknowledge the commit nor raise ERROR or FATAL. The latter would
|
2015-12-18 18:43:52 +01:00
|
|
|
* lead the client to believe that the transaction aborted, which
|
2011-04-10 17:42:00 +02:00
|
|
|
* is not true: it's already committed locally. The former is no good
|
|
|
|
* either: the client has requested synchronous replication, and is
|
|
|
|
* entitled to assume that an acknowledged commit is also replicated,
|
2011-06-21 23:33:20 +02:00
|
|
|
* which might not be true. So in this case we issue a WARNING (which
|
2011-04-10 17:42:00 +02:00
|
|
|
* some clients may be able to interpret) and shut off further output.
|
|
|
|
* We do NOT reset ProcDiePending, so that the process will die after
|
|
|
|
* the commit is cleaned up.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
if (ProcDiePending)
|
|
|
|
{
|
|
|
|
ereport(WARNING,
|
|
|
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
2011-03-18 15:20:22 +01:00
|
|
|
errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
|
2011-06-21 23:33:20 +02:00
|
|
|
errdetail("The transaction has already committed locally, but might not have been replicated to the standby.")));
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
whereToSendOutput = DestNone;
|
|
|
|
SyncRepCancelWait();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It's unclear what to do if a query cancel interrupt arrives. We
|
|
|
|
* can't actually abort at this point, but ignoring the interrupt
|
2011-04-10 17:42:00 +02:00
|
|
|
* altogether is not helpful, so we just terminate the wait with a
|
|
|
|
* suitable warning.
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
*/
|
|
|
|
if (QueryCancelPending)
|
|
|
|
{
|
|
|
|
QueryCancelPending = false;
|
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("canceling wait for synchronous replication due to user request"),
|
2011-06-21 23:33:20 +02:00
|
|
|
errdetail("The transaction has already committed locally, but might not have been replicated to the standby.")));
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
SyncRepCancelWait();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* If the postmaster dies, we'll probably never get an
|
2011-06-09 20:32:50 +02:00
|
|
|
* acknowledgement, because all the wal sender processes will exit. So
|
|
|
|
* just bail out.
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
*/
|
Introduce a pipe between postmaster and each backend, which can be used to
detect postmaster death. Postmaster keeps the write-end of the pipe open,
so when it dies, children get EOF in the read-end. That can conveniently
be waited for in select(), which allows eliminating some of the polling
loops that check for postmaster death. This patch doesn't yet change all
the loops to use the new mechanism, expect a follow-on patch to do that.
This changes the interface to WaitLatch, so that it takes as argument a
bitmask of events that it waits for. Possible events are latch set, timeout,
postmaster death, and socket becoming readable or writeable.
The pipe method behaves slightly differently from the kill() method
previously used in PostmasterIsAlive() in the case that postmaster has died,
but its parent has not yet read its exit code with waitpid(). The pipe
returns EOF as soon as the process dies, but kill() continues to return
true until waitpid() has been called (IOW while the process is a zombie).
Because of that, change PostmasterIsAlive() to use the pipe too, otherwise
WaitLatch() would return immediately with WL_POSTMASTER_DEATH, while
PostmasterIsAlive() would claim it's still alive. That could easily lead to
busy-waiting while postmaster is in zombie state.
Peter Geoghegan with further changes by me, reviewed by Fujii Masao and
Florian Pflug.
2011-07-08 17:27:49 +02:00
|
|
|
if (!PostmasterIsAlive())
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
{
|
|
|
|
ProcDiePending = true;
|
|
|
|
whereToSendOutput = DestNone;
|
|
|
|
SyncRepCancelWait();
|
|
|
|
break;
|
|
|
|
}
|
2011-08-09 21:30:45 +02:00
|
|
|
|
|
|
|
/*
|
2012-06-10 21:20:04 +02:00
|
|
|
* Wait on latch. Any condition that should wake us up will set the
|
|
|
|
* latch, so no need for timeout.
|
2011-08-09 21:30:45 +02:00
|
|
|
*/
|
2015-01-14 18:45:22 +01:00
|
|
|
WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1);
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* WalSender has checked our LSN and has removed us from queue. Clean up
|
|
|
|
* state and leave. It's OK to reset these shared memory fields without
|
|
|
|
* holding SyncRepLock, because any walsenders will ignore us anyway when
|
|
|
|
* we're not on the queue.
|
|
|
|
*/
|
|
|
|
Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
|
|
|
|
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
|
2012-06-24 17:51:37 +02:00
|
|
|
MyProc->waitLSN = 0;
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
|
|
|
|
if (new_status)
|
|
|
|
{
|
|
|
|
/* Reset ps display */
|
|
|
|
set_ps_display(new_status, false);
|
|
|
|
pfree(new_status);
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-01-24 21:22:37 +01:00
|
|
|
* Insert MyProc into the specified SyncRepQueue, maintaining sorted invariant.
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
2011-03-10 21:56:18 +01:00
|
|
|
* Usually we will go at tail of queue, though it's possible that we arrive
|
2011-03-07 00:39:14 +01:00
|
|
|
* here out of order, so start at tail and work back to insertion point.
|
|
|
|
*/
|
|
|
|
static void
|
2012-01-24 21:22:37 +01:00
|
|
|
SyncRepQueueInsert(int mode)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
PGPROC *proc;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
|
|
|
|
proc = (PGPROC *) SHMQueuePrev(&(WalSndCtl->SyncRepQueue[mode]),
|
|
|
|
&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
|
|
|
|
while (proc)
|
|
|
|
{
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Stop at the queue element that we should after to ensure the queue
|
|
|
|
* is ordered by LSN.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
2012-12-28 17:06:15 +01:00
|
|
|
if (proc->waitLSN < MyProc->waitLSN)
|
2011-03-07 00:39:14 +01:00
|
|
|
break;
|
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
proc = (PGPROC *) SHMQueuePrev(&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
&(proc->syncRepLinks),
|
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (proc)
|
|
|
|
SHMQueueInsertAfter(&(proc->syncRepLinks), &(MyProc->syncRepLinks));
|
|
|
|
else
|
2012-01-24 21:22:37 +01:00
|
|
|
SHMQueueInsertAfter(&(WalSndCtl->SyncRepQueue[mode]), &(MyProc->syncRepLinks));
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
|
|
|
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
/*
|
|
|
|
* Acquire SyncRepLock and cancel any wait currently in progress.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SyncRepCancelWait(void)
|
|
|
|
{
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
|
|
|
if (!SHMQueueIsDetached(&(MyProc->syncRepLinks)))
|
|
|
|
SHMQueueDelete(&(MyProc->syncRepLinks));
|
|
|
|
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
}
|
|
|
|
|
2011-03-07 00:39:14 +01:00
|
|
|
void
|
2011-08-10 18:20:30 +02:00
|
|
|
SyncRepCleanupAtProcExit(void)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
|
|
|
if (!SHMQueueIsDetached(&(MyProc->syncRepLinks)))
|
|
|
|
{
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
|
|
|
SHMQueueDelete(&(MyProc->syncRepLinks));
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ===========================================================
|
|
|
|
* Synchronous Replication functions for wal sender processes
|
|
|
|
* ===========================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take any action required to initialise sync rep state from config
|
|
|
|
* data. Called at WALSender startup and after each SIGHUP.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SyncRepInitConfig(void)
|
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
int priority;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine if we are a potential sync standby and remember the result
|
|
|
|
* for handling replies from standby.
|
|
|
|
*/
|
|
|
|
priority = SyncRepGetStandbyPriority();
|
|
|
|
if (MyWalSnd->sync_standby_priority != priority)
|
|
|
|
{
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
|
|
|
MyWalSnd->sync_standby_priority = priority;
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
ereport(DEBUG1,
|
2011-04-10 17:42:00 +02:00
|
|
|
(errmsg("standby \"%s\" now has synchronous standby priority %u",
|
|
|
|
application_name, priority)));
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-12 12:39:36 +01:00
|
|
|
/*
|
|
|
|
* Find the WAL sender servicing the synchronous standby with the lowest
|
|
|
|
* priority value, or NULL if no synchronous standby is connected. If there
|
|
|
|
* are multiple standbys with the same lowest priority value, the first one
|
|
|
|
* found is selected. The caller must hold SyncRepLock.
|
|
|
|
*/
|
|
|
|
WalSnd *
|
|
|
|
SyncRepGetSynchronousStandby(void)
|
|
|
|
{
|
|
|
|
WalSnd *result = NULL;
|
|
|
|
int result_priority = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < max_wal_senders; i++)
|
|
|
|
{
|
|
|
|
/* Use volatile pointer to prevent code rearrangement */
|
|
|
|
volatile WalSnd *walsnd = &WalSndCtl->walsnds[i];
|
|
|
|
int this_priority;
|
|
|
|
|
|
|
|
/* Must be active */
|
|
|
|
if (walsnd->pid == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Must be streaming */
|
|
|
|
if (walsnd->state != WALSNDSTATE_STREAMING)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Must be synchronous */
|
|
|
|
this_priority = walsnd->sync_standby_priority;
|
|
|
|
if (this_priority == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Must have a lower priority value than any previous ones */
|
|
|
|
if (result != NULL && result_priority <= this_priority)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Must have a valid flush position */
|
|
|
|
if (XLogRecPtrIsInvalid(walsnd->flush))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
result = (WalSnd *) walsnd;
|
|
|
|
result_priority = this_priority;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If priority is equal to 1, there cannot be any other WAL senders
|
|
|
|
* with a lower priority, so we're done.
|
|
|
|
*/
|
|
|
|
if (this_priority == 1)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-03-07 00:39:14 +01:00
|
|
|
/*
|
|
|
|
* Update the LSNs on each queue based upon our latest state. This
|
|
|
|
* implements a simple policy of first-valid-standby-releases-waiter.
|
|
|
|
*
|
|
|
|
* Other policies are possible, which would change what we do here and what
|
|
|
|
* perhaps also which information we store as well.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SyncRepReleaseWaiters(void)
|
|
|
|
{
|
|
|
|
volatile WalSndCtlData *walsndctl = WalSndCtl;
|
2014-12-12 12:39:36 +01:00
|
|
|
WalSnd *syncWalSnd;
|
2012-01-24 21:22:37 +01:00
|
|
|
int numwrite = 0;
|
|
|
|
int numflush = 0;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If this WALSender is serving a standby that is not on the list of
|
2011-04-10 17:42:00 +02:00
|
|
|
* potential standbys then we have nothing to do. If we are still starting
|
2012-07-04 15:10:46 +02:00
|
|
|
* up, still running base backup or the current flush position is still
|
|
|
|
* invalid, then leave quickly also.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
|
|
|
if (MyWalSnd->sync_standby_priority == 0 ||
|
2012-07-04 15:10:46 +02:00
|
|
|
MyWalSnd->state < WALSNDSTATE_STREAMING ||
|
|
|
|
XLogRecPtrIsInvalid(MyWalSnd->flush))
|
2011-03-07 00:39:14 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* We're a potential sync standby. Release waiters if we are the highest
|
2014-12-12 12:39:36 +01:00
|
|
|
* priority standby.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
2014-12-12 12:39:36 +01:00
|
|
|
syncWalSnd = SyncRepGetSynchronousStandby();
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2014-12-12 12:39:36 +01:00
|
|
|
/* We should have found ourselves at least */
|
|
|
|
Assert(syncWalSnd != NULL);
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we aren't managing the highest priority standby then just leave.
|
|
|
|
*/
|
|
|
|
if (syncWalSnd != MyWalSnd)
|
|
|
|
{
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
announce_next_takeover = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
/*
|
2012-06-10 21:20:04 +02:00
|
|
|
* Set the lsn first so that when we wake backends they will release up to
|
|
|
|
* this location.
|
2012-01-24 21:22:37 +01:00
|
|
|
*/
|
2012-12-28 17:06:15 +01:00
|
|
|
if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < MyWalSnd->write)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
2012-01-24 21:22:37 +01:00
|
|
|
walsndctl->lsn[SYNC_REP_WAIT_WRITE] = MyWalSnd->write;
|
|
|
|
numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE);
|
|
|
|
}
|
2012-12-28 17:06:15 +01:00
|
|
|
if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < MyWalSnd->flush)
|
2012-01-24 21:22:37 +01:00
|
|
|
{
|
|
|
|
walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = MyWalSnd->flush;
|
|
|
|
numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH);
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
elog(DEBUG3, "released %d procs up to write %X/%X, %d procs up to flush %X/%X",
|
2012-06-24 17:51:37 +02:00
|
|
|
numwrite, (uint32) (MyWalSnd->write >> 32), (uint32) MyWalSnd->write,
|
2013-05-29 22:58:43 +02:00
|
|
|
numflush, (uint32) (MyWalSnd->flush >> 32), (uint32) MyWalSnd->flush);
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we are managing the highest priority standby, though we weren't
|
|
|
|
* prior to this, then announce we are now the sync standby.
|
|
|
|
*/
|
|
|
|
if (announce_next_takeover)
|
|
|
|
{
|
|
|
|
announce_next_takeover = false;
|
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("standby \"%s\" is now the synchronous standby with priority %u",
|
|
|
|
application_name, MyWalSnd->sync_standby_priority)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if we are in the list of sync standbys, and if so, determine
|
|
|
|
* priority sequence. Return priority if set, or zero to indicate that
|
|
|
|
* we are not a potential sync standby.
|
|
|
|
*
|
|
|
|
* Compare the parameter SyncRepStandbyNames against the application_name
|
|
|
|
* for this WALSender, or allow any name if we find a wildcard "*".
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
SyncRepGetStandbyPriority(void)
|
|
|
|
{
|
|
|
|
char *rawstring;
|
|
|
|
List *elemlist;
|
|
|
|
ListCell *l;
|
|
|
|
int priority = 0;
|
|
|
|
bool found = false;
|
|
|
|
|
2011-07-19 04:40:03 +02:00
|
|
|
/*
|
2012-06-10 21:20:04 +02:00
|
|
|
* Since synchronous cascade replication is not allowed, we always set the
|
|
|
|
* priority of cascading walsender to zero.
|
2011-07-19 04:40:03 +02:00
|
|
|
*/
|
|
|
|
if (am_cascading_walsender)
|
|
|
|
return 0;
|
|
|
|
|
2011-03-07 00:39:14 +01:00
|
|
|
/* Need a modifiable copy of string */
|
|
|
|
rawstring = pstrdup(SyncRepStandbyNames);
|
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawstring, ',', &elemlist))
|
|
|
|
{
|
|
|
|
/* syntax error in list */
|
|
|
|
pfree(rawstring);
|
|
|
|
list_free(elemlist);
|
2011-03-10 22:24:52 +01:00
|
|
|
/* GUC machinery will have already complained - no need to do again */
|
2011-03-07 00:39:14 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach(l, elemlist)
|
|
|
|
{
|
|
|
|
char *standby_name = (char *) lfirst(l);
|
|
|
|
|
|
|
|
priority++;
|
|
|
|
|
|
|
|
if (pg_strcasecmp(standby_name, application_name) == 0 ||
|
|
|
|
pg_strcasecmp(standby_name, "*") == 0)
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pfree(rawstring);
|
|
|
|
list_free(elemlist);
|
|
|
|
|
|
|
|
return (found ? priority : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Walk the specified queue from head. Set the state of any backends that
|
2012-01-24 21:22:37 +01:00
|
|
|
* need to be woken, remove them from the queue, and then wake them.
|
|
|
|
* Pass all = true to wake whole queue; otherwise, just wake up to
|
|
|
|
* the walsender's LSN.
|
2011-03-07 00:39:14 +01:00
|
|
|
*
|
|
|
|
* Must hold SyncRepLock.
|
|
|
|
*/
|
2015-03-26 02:34:08 +01:00
|
|
|
static int
|
2012-01-24 21:22:37 +01:00
|
|
|
SyncRepWakeQueue(bool all, int mode)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
|
|
|
volatile WalSndCtlData *walsndctl = WalSndCtl;
|
2011-04-10 17:42:00 +02:00
|
|
|
PGPROC *proc = NULL;
|
|
|
|
PGPROC *thisproc = NULL;
|
|
|
|
int numprocs = 0;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
|
|
|
|
Assert(SyncRepQueueIsOrderedByLSN(mode));
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]),
|
|
|
|
&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
|
|
|
|
while (proc)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Assume the queue is ordered by LSN
|
|
|
|
*/
|
2012-12-28 17:06:15 +01:00
|
|
|
if (!all && walsndctl->lsn[mode] < proc->waitLSN)
|
2011-03-07 00:39:14 +01:00
|
|
|
return numprocs;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move to next proc, so we can delete thisproc from the queue.
|
|
|
|
* thisproc is valid, proc may be NULL after this.
|
|
|
|
*/
|
|
|
|
thisproc = proc;
|
2012-01-24 21:22:37 +01:00
|
|
|
proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
&(proc->syncRepLinks),
|
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Set state to complete; see SyncRepWaitForLSN() for discussion of
|
|
|
|
* the various states.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
|
|
|
thisproc->syncRepState = SYNC_REP_WAIT_COMPLETE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove thisproc from queue.
|
|
|
|
*/
|
|
|
|
SHMQueueDelete(&(thisproc->syncRepLinks));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wake only when we have set state and removed from queue.
|
|
|
|
*/
|
2011-08-10 18:20:30 +02:00
|
|
|
SetLatch(&(thisproc->procLatch));
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
numprocs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numprocs;
|
|
|
|
}
|
|
|
|
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
/*
|
2012-01-30 15:34:25 +01:00
|
|
|
* The checkpointer calls this as needed to update the shared
|
2011-03-19 02:43:45 +01:00
|
|
|
* sync_standbys_defined flag, so that backends don't remain permanently wedged
|
|
|
|
* if synchronous_standby_names is unset. It's safe to check the current value
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
* without the lock, because it's only ever updated by one process. But we
|
|
|
|
* must take the lock to change it.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SyncRepUpdateSyncStandbysDefined(void)
|
|
|
|
{
|
|
|
|
bool sync_standbys_defined = SyncStandbysDefined();
|
|
|
|
|
|
|
|
if (sync_standbys_defined != WalSndCtl->sync_standbys_defined)
|
|
|
|
{
|
|
|
|
LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If synchronous_standby_names has been reset to empty, it's futile
|
|
|
|
* for backends to continue to waiting. Since the user no longer
|
|
|
|
* wants synchronous replication, we'd better wake them up.
|
|
|
|
*/
|
|
|
|
if (!sync_standbys_defined)
|
2012-01-24 21:22:37 +01:00
|
|
|
{
|
2012-06-10 21:20:04 +02:00
|
|
|
int i;
|
2012-01-24 21:22:37 +01:00
|
|
|
|
|
|
|
for (i = 0; i < NUM_SYNC_REP_WAIT_MODE; i++)
|
|
|
|
SyncRepWakeQueue(true, i);
|
|
|
|
}
|
Fix various possible problems with synchronous replication.
1. Don't ignore query cancel interrupts. Instead, if the user asks to
cancel the query after we've already committed it, but before it's on
the standby, just emit a warning and let the COMMIT finish.
2. Don't ignore die interrupts (pg_terminate_backend or fast shutdown).
Instead, emit a warning message and close the connection without
acknowledging the commit. Other backends will still see the effect of
the commit, but there's no getting around that; it's too late to abort
at this point, and ignoring die interrupts altogether doesn't seem like
a good idea.
3. If synchronous_standby_names becomes empty, wake up all backends
waiting for synchronous replication to complete. Without this, someone
attempting to shut synchronous replication off could easily wedge the
entire system instead.
4. Avoid depending on the assumption that if a walsender updates
MyProc->syncRepState, we'll see the change even if we read it without
holding the lock. The window for this appears to be quite narrow (and
probably doesn't exist at all on machines with strong memory ordering)
but protecting against it is practically free, so do that.
5. Remove useless state SYNC_REP_MUST_DISCONNECT, which isn't needed and
doesn't actually do anything.
There's still some further work needed here to make the behavior of fast
shutdown plausible, but that looks complex, so I'm leaving it for a
separate commit. Review by Fujii Masao.
2011-03-17 18:10:42 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only allow people to join the queue when there are synchronous
|
|
|
|
* standbys defined. Without this interlock, there's a race
|
|
|
|
* condition: we might wake up all the current waiters; then, some
|
|
|
|
* backend that hasn't yet reloaded its config might go to sleep on
|
|
|
|
* the queue (and never wake up). This prevents that.
|
|
|
|
*/
|
|
|
|
WalSndCtl->sync_standbys_defined = sync_standbys_defined;
|
|
|
|
|
|
|
|
LWLockRelease(SyncRepLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-07 00:39:14 +01:00
|
|
|
#ifdef USE_ASSERT_CHECKING
|
|
|
|
static bool
|
2012-01-24 21:22:37 +01:00
|
|
|
SyncRepQueueIsOrderedByLSN(int mode)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
PGPROC *proc = NULL;
|
|
|
|
XLogRecPtr lastLSN;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
Assert(mode >= 0 && mode < NUM_SYNC_REP_WAIT_MODE);
|
|
|
|
|
2012-06-24 17:51:37 +02:00
|
|
|
lastLSN = 0;
|
2011-03-07 00:39:14 +01:00
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]),
|
|
|
|
&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
|
|
|
|
while (proc)
|
|
|
|
{
|
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* Check the queue is ordered by LSN and that multiple procs don't
|
|
|
|
* have matching LSNs
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
2012-12-28 17:06:15 +01:00
|
|
|
if (proc->waitLSN <= lastLSN)
|
2011-03-07 00:39:14 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
lastLSN = proc->waitLSN;
|
|
|
|
|
2012-01-24 21:22:37 +01:00
|
|
|
proc = (PGPROC *) SHMQueueNext(&(WalSndCtl->SyncRepQueue[mode]),
|
2011-03-07 00:39:14 +01:00
|
|
|
&(proc->syncRepLinks),
|
|
|
|
offsetof(PGPROC, syncRepLinks));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ===========================================================
|
|
|
|
* Synchronous Replication functions executed by any process
|
|
|
|
* ===========================================================
|
|
|
|
*/
|
|
|
|
|
2011-04-07 06:11:01 +02:00
|
|
|
bool
|
|
|
|
check_synchronous_standby_names(char **newval, void **extra, GucSource source)
|
2011-03-07 00:39:14 +01:00
|
|
|
{
|
|
|
|
char *rawstring;
|
|
|
|
List *elemlist;
|
|
|
|
|
|
|
|
/* Need a modifiable copy of string */
|
2011-04-07 06:11:01 +02:00
|
|
|
rawstring = pstrdup(*newval);
|
2011-03-07 00:39:14 +01:00
|
|
|
|
|
|
|
/* Parse string into list of identifiers */
|
|
|
|
if (!SplitIdentifierString(rawstring, ',', &elemlist))
|
|
|
|
{
|
|
|
|
/* syntax error in list */
|
2011-04-07 06:11:01 +02:00
|
|
|
GUC_check_errdetail("List syntax is invalid.");
|
2011-03-07 00:39:14 +01:00
|
|
|
pfree(rawstring);
|
|
|
|
list_free(elemlist);
|
2011-04-07 06:11:01 +02:00
|
|
|
return false;
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Any additional validation of standby names should go here.
|
|
|
|
*
|
|
|
|
* Don't attempt to set WALSender priority because this is executed by
|
2011-04-10 17:42:00 +02:00
|
|
|
* postmaster at startup, not WALSender, so the application_name is not
|
|
|
|
* yet correctly set.
|
2011-03-07 00:39:14 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
pfree(rawstring);
|
|
|
|
list_free(elemlist);
|
|
|
|
|
2011-04-07 06:11:01 +02:00
|
|
|
return true;
|
2011-03-07 00:39:14 +01:00
|
|
|
}
|
2012-01-24 21:22:37 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
assign_synchronous_commit(int newval, void *extra)
|
|
|
|
{
|
|
|
|
switch (newval)
|
|
|
|
{
|
|
|
|
case SYNCHRONOUS_COMMIT_REMOTE_WRITE:
|
|
|
|
SyncRepWaitMode = SYNC_REP_WAIT_WRITE;
|
|
|
|
break;
|
|
|
|
case SYNCHRONOUS_COMMIT_REMOTE_FLUSH:
|
|
|
|
SyncRepWaitMode = SYNC_REP_WAIT_FLUSH;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SyncRepWaitMode = SYNC_REP_NO_WAIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|