Commit 240067b3 authored by Robert Haas's avatar Robert Haas

Merge synchronous_replication setting into synchronous_commit.

This means one less thing to configure when setting up synchronous
replication, and also avoids some ambiguity around what the behavior
should be when the settings of these variables conflict.

Fujii Masao, with additional hacking by me.
parent fc3459d7
...@@ -1507,8 +1507,9 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -1507,8 +1507,9 @@ SET ENABLE_SEQSCAN TO OFF;
<para> <para>
Specifies whether transaction commit will wait for WAL records Specifies whether transaction commit will wait for WAL records
to be written to disk before the command returns a <quote>success</> to be written to disk before the command returns a <quote>success</>
indication to the client. The default, and safe, setting is indication to the client. Valid values are <literal>on</>,
<literal>on</>. When <literal>off</>, there can be a delay between <literal>local</>, and <literal>off</>. The default, and safe, value
is <literal>on</>. When <literal>off</>, there can be a delay between
when success is reported to the client and when the transaction is when success is reported to the client and when the transaction is
really guaranteed to be safe against a server crash. (The maximum really guaranteed to be safe against a server crash. (The maximum
delay is three times <xref linkend="guc-wal-writer-delay">.) Unlike delay is three times <xref linkend="guc-wal-writer-delay">.) Unlike
...@@ -1522,6 +1523,19 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -1522,6 +1523,19 @@ SET ENABLE_SEQSCAN TO OFF;
exact certainty about the durability of a transaction. For more exact certainty about the durability of a transaction. For more
discussion see <xref linkend="wal-async-commit">. discussion see <xref linkend="wal-async-commit">.
</para> </para>
<para>
If <xref linkend="guc-synchronous-standby-names"> is set, this
parameter also controls whether or not transaction commit will wait
for the transaction's WAL records to be flushed to disk and replicated
to the standby server. The commit wait will last until a reply from
the current synchronous standby indicates it has written the commit
record of the transaction to durable storage. If synchronous
replication is in use, it will normally be sensible either to wait
both for WAL records to reach both the local and remote disks, or
to allow the transaction to commit asynchronously. However, the
special value <literal>local</> is available for transactions that
wish to wait for local flush to disk, but not synchronous replication.
</para>
<para> <para>
This parameter can be changed at any time; the behavior for any This parameter can be changed at any time; the behavior for any
one transaction is determined by the setting in effect when it one transaction is determined by the setting in effect when it
...@@ -2057,39 +2071,6 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -2057,39 +2071,6 @@ SET ENABLE_SEQSCAN TO OFF;
</para> </para>
<variablelist> <variablelist>
<varlistentry id="guc-synchronous-replication" xreflabel="synchronous_replication">
<term><varname>synchronous_replication</varname> (<type>boolean</type>)</term>
<indexterm>
<primary><varname>synchronous_replication</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies whether transaction commit will wait for WAL records
to be replicated before the command returns a <quote>success</>
indication to the client. The default setting is <literal>off</>.
When <literal>on</>, there will be a delay while the client waits
for confirmation of successful replication. That delay will
increase depending upon the physical distance and network activity
between primary and standby. The commit wait will last until a
reply from the current synchronous standby indicates it has written
the commit record of the transaction to durable storage. This
parameter has no effect if
<xref linkend="guc-synchronous-standby-names"> is empty or
<xref linkend="guc-max-wal-senders"> is zero.
</para>
<para>
This parameter can be changed at any time; the
behavior for any one transaction is determined by the setting in
effect when it commits. It is therefore possible, and useful, to have
some transactions replicate synchronously and others asynchronously.
For example, to make a single multistatement transaction commit
asynchronously when the default is synchronous replication, issue
<command>SET LOCAL synchronous_replication TO OFF</> within the
transaction.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-synchronous-standby-names" xreflabel="synchronous_standby_names"> <varlistentry id="guc-synchronous-standby-names" xreflabel="synchronous_standby_names">
<term><varname>synchronous_standby_names</varname> (<type>string</type>)</term> <term><varname>synchronous_standby_names</varname> (<type>string</type>)</term>
<indexterm> <indexterm>
...@@ -2098,7 +2079,7 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -2098,7 +2079,7 @@ SET ENABLE_SEQSCAN TO OFF;
<listitem> <listitem>
<para> <para>
Specifies a priority ordered list of standby names that can offer Specifies a priority ordered list of standby names that can offer
synchronous replication. At any one time there will be just one synchronous replication. At any one time there will be at most one
synchronous standby that will wake sleeping users following commit. synchronous standby that will wake sleeping users following commit.
The synchronous standby will be the first named standby that is The synchronous standby will be the first named standby that is
both currently connected and streaming in real-time to the standby both currently connected and streaming in real-time to the standby
...@@ -2114,18 +2095,17 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -2114,18 +2095,17 @@ SET ENABLE_SEQSCAN TO OFF;
not enforced for uniqueness. In case of duplicates one of the standbys not enforced for uniqueness. In case of duplicates one of the standbys
will be chosen to be the synchronous standby, though exactly which will be chosen to be the synchronous standby, though exactly which
one is indeterminate. one is indeterminate.
</para>
<para>
No value is set by default.
The special entry <literal>*</> matches any application_name, including The special entry <literal>*</> matches any application_name, including
the default application name of <literal>walreceiver</>. the default application name of <literal>walreceiver</>.
</para> </para>
<para> <para>
If a standby is removed from the list of servers then it will stop If no synchronous standby names are specified, then synchronous
being the synchronous standby, allowing another to take its place. replication is not enabled and transaction commit will never wait for
If the list is empty, synchronous replication will not be replication. This is the default configuration. Even when
possible, whatever the setting of <varname>synchronous_replication</>. synchronous replication is enabled, individual transactions can be
Standbys may also be added to the list without restarting the server. configured not to wait for replication by setting the
<xref linkend="guc-synchronous-commit"> parameter to
<literal>local</> or <literal>off</>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -929,19 +929,18 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' ...@@ -929,19 +929,18 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
<title>Basic Configuration</title> <title>Basic Configuration</title>
<para> <para>
All parameters have useful default values, so we can enable Once streaming replication has been configured, configuring synchronous
synchronous replication easily just by setting this on the primary: replication requires only one additional configuration step:
<xref linkend="guc-synchronous-standby-names"> must be set to
<programlisting> a non-empty value. <varname>synchronous_commit</> must also be set to
synchronous_replication = on <literal>on</>, but since this is the default value, typically no change is
</programlisting> required. This configuration will cause each commit to wait for
confirmation that the standby has written the commit record to durable
When <varname>synchronous_replication</> is set, a commit will wait storage, even if that takes a very long time.
for confirmation that the standby has received the commit record, <varname>synchronous_commit</> can be set by individual
even if that takes a very long time.
<varname>synchronous_replication</> can be set by individual
users, so can be configured in the configuration file, for particular users, so can be configured in the configuration file, for particular
users or databases, or dynamically by applications. users or databases, or dynamically by applications, in order to control
the durability guarantee on a per-transaction basis.
</para> </para>
<para> <para>
...@@ -959,17 +958,10 @@ synchronous_replication = on ...@@ -959,17 +958,10 @@ synchronous_replication = on
</para> </para>
<para> <para>
Users will stop waiting if a fast shutdown is requested, though the Users will stop waiting if a fast shutdown is requested. However, as
server does not fully shutdown until all outstanding WAL records are when using asynchronous replication, the server will does not fully
transferred to standby servers. shutdown until all outstanding WAL records are transferred to the currently
</para> connected standby servers.
<para>
Note also that <varname>synchronous_commit</> is used when the user
specifies <varname>synchronous_replication</>, overriding even an
explicit setting of <varname>synchronous_commit</> to <literal>off</>.
This is because we must write WAL to disk on primary before we replicate
to ensure the standby never gets ahead of the primary.
</para> </para>
</sect3> </sect3>
...@@ -1019,9 +1011,9 @@ synchronous_replication = on ...@@ -1019,9 +1011,9 @@ synchronous_replication = on
<title>Planning for High Availability</title> <title>Planning for High Availability</title>
<para> <para>
Commits made when synchronous_replication is set will wait until Commits made when <varname>synchronous_commit</> is set to <literal>on</>
the sync standby responds. The response may never occur if the last, will wait until the sync standby responds. The response may never occur
or only, standby should crash. if the last, or only, standby should crash.
</para> </para>
<para> <para>
...@@ -1073,8 +1065,8 @@ synchronous_replication = on ...@@ -1073,8 +1065,8 @@ synchronous_replication = on
If you need to re-create a standby server while transactions are If you need to re-create a standby server while transactions are
waiting, make sure that the commands to run pg_start_backup() and waiting, make sure that the commands to run pg_start_backup() and
pg_stop_backup() are run in a session with pg_stop_backup() are run in a session with
synchronous_replication = off, otherwise those requests will wait <varname>synchronous_commit</> = <literal>off</>, otherwise those
forever for the standby to appear. requests will wait forever for the standby to appear.
</para> </para>
</sect3> </sect3>
......
...@@ -651,14 +651,15 @@ ...@@ -651,14 +651,15 @@
</para> </para>
<para> <para>
This allows the primary to wait for a standby to write the transaction
information to disk before acknowledging the commit.
One standby at a time can take the role of the synchronous standby, One standby at a time can take the role of the synchronous standby,
as controlled by the as controlled by the
<link linkend="guc-synchronous-standby-names"><varname>synchronous_standby_names</varname></link> <link linkend="guc-synchronous-standby-names"><varname>synchronous_standby_names</varname></link>
setting. Synchronous replication can be enabled or disabled on a setting. Synchronous replication can be enabled or disabled on a
per-transaction basis using the per-transaction basis using the
<link linkend="guc-synchronous-replication"><varname>synchronous_replication</></link> <link linkend="guc-synchronous-commit"><varname>synchronous_commit</></link>
setting. This allows the primary to wait for a standby to write the setting.
transaction information to disk before acknowledging the commit.
</para> </para>
</listitem> </listitem>
......
...@@ -68,7 +68,7 @@ bool XactReadOnly; ...@@ -68,7 +68,7 @@ bool XactReadOnly;
bool DefaultXactDeferrable = false; bool DefaultXactDeferrable = false;
bool XactDeferrable; bool XactDeferrable;
bool XactSyncCommit = true; int synchronous_commit = SYNCHRONOUS_COMMIT_ON;
int CommitDelay = 0; /* precommit delay in microseconds */ int CommitDelay = 0; /* precommit delay in microseconds */
int CommitSiblings = 5; /* # concurrent xacts needed to sleep */ int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
...@@ -1056,7 +1056,8 @@ RecordTransactionCommit(void) ...@@ -1056,7 +1056,8 @@ RecordTransactionCommit(void)
* if all to-be-deleted tables are temporary though, since they are lost * if all to-be-deleted tables are temporary though, since they are lost
* anyway if we crash.) * anyway if we crash.)
*/ */
if ((wrote_xlog && XactSyncCommit) || forceSyncCommit || nrels > 0 || SyncRepRequested()) if ((wrote_xlog && synchronous_commit >= SYNCHRONOUS_COMMIT_LOCAL) ||
forceSyncCommit || nrels > 0)
{ {
/* /*
* Synchronous commit case: * Synchronous commit case:
......
...@@ -1531,7 +1531,8 @@ AutoVacWorkerMain(int argc, char *argv[]) ...@@ -1531,7 +1531,8 @@ AutoVacWorkerMain(int argc, char *argv[])
* if we are waiting for standbys to connect. This is important to * if we are waiting for standbys to connect. This is important to
* ensure we aren't blocked from performing anti-wraparound tasks. * ensure we aren't blocked from performing anti-wraparound tasks.
*/ */
SetConfigOption("synchronous_replication", "off", PGC_SUSET, PGC_S_OVERRIDE); if (synchronous_commit == SYNCHRONOUS_COMMIT_ON)
SetConfigOption("synchronous_commit", "local", PGC_SUSET, PGC_S_OVERRIDE);
/* /*
* Get the info about the database we're going to work on. * Get the info about the database we're going to work on.
......
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
#include "utils/ps_status.h" #include "utils/ps_status.h"
/* User-settable parameters for sync rep */ /* User-settable parameters for sync rep */
bool synchronous_replication = false; /* Only set in user backends */
char *SyncRepStandbyNames; char *SyncRepStandbyNames;
#define SyncStandbysDefined() \ #define SyncStandbysDefined() \
......
...@@ -350,6 +350,23 @@ static const struct config_enum_entry constraint_exclusion_options[] = { ...@@ -350,6 +350,23 @@ static const struct config_enum_entry constraint_exclusion_options[] = {
{NULL, 0, false} {NULL, 0, false}
}; };
/*
* Although only "on", "off", and "local" are documented, we
* accept all the likely variants of "on" and "off".
*/
static const struct config_enum_entry synchronous_commit_options[] = {
{"local", SYNCHRONOUS_COMMIT_LOCAL, false},
{"on", SYNCHRONOUS_COMMIT_ON, false},
{"off", SYNCHRONOUS_COMMIT_OFF, false},
{"true", SYNCHRONOUS_COMMIT_ON, true},
{"false", SYNCHRONOUS_COMMIT_OFF, true},
{"yes", SYNCHRONOUS_COMMIT_ON, true},
{"no", SYNCHRONOUS_COMMIT_OFF, true},
{"1", SYNCHRONOUS_COMMIT_ON, true},
{"0", SYNCHRONOUS_COMMIT_OFF, true},
{NULL, 0, false}
};
/* /*
* Options for enum values stored in other modules * Options for enum values stored in other modules
*/ */
...@@ -746,22 +763,6 @@ static struct config_bool ConfigureNamesBool[] = ...@@ -746,22 +763,6 @@ static struct config_bool ConfigureNamesBool[] =
&enableFsync, &enableFsync,
true, NULL, NULL true, NULL, NULL
}, },
{
{"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
gettext_noop("Sets immediate fsync at commit."),
NULL
},
&XactSyncCommit,
true, NULL, NULL
},
{
{"synchronous_replication", PGC_USERSET, WAL_REPLICATION,
gettext_noop("Requests synchronous replication."),
NULL
},
&synchronous_replication,
false, NULL, NULL
},
{ {
{"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS, {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
gettext_noop("Continues processing past damaged page headers."), gettext_noop("Continues processing past damaged page headers."),
...@@ -2908,6 +2909,16 @@ static struct config_enum ConfigureNamesEnum[] = ...@@ -2908,6 +2909,16 @@ static struct config_enum ConfigureNamesEnum[] =
assign_session_replication_role, NULL assign_session_replication_role, NULL
}, },
{
{"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
gettext_noop("Sets the current transaction's synchronization level."),
NULL
},
&synchronous_commit,
SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
NULL, NULL
},
{ {
{"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS, {"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
gettext_noop("Enables logging of recovery-related debugging information."), gettext_noop("Enables logging of recovery-related debugging information."),
......
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
#wal_level = minimal # minimal, archive, or hot_standby #wal_level = minimal # minimal, archive, or hot_standby
# (change requires restart) # (change requires restart)
#fsync = on # turns forced synchronization on or off #fsync = on # turns forced synchronization on or off
#synchronous_commit = on # immediate fsync at commit #synchronous_commit = on # synchronization level; on, off, or local
#wal_sync_method = fsync # the default is the first option #wal_sync_method = fsync # the default is the first option
# supported by the operating system: # supported by the operating system:
# open_datasync # open_datasync
...@@ -184,10 +184,6 @@ ...@@ -184,10 +184,6 @@
#archive_timeout = 0 # force a logfile segment switch after this #archive_timeout = 0 # force a logfile segment switch after this
# number of seconds; 0 disables # number of seconds; 0 disables
# - Replication - User Settings
#synchronous_replication = off # does commit wait for reply from standby
# - Streaming Replication - Server Settings # - Streaming Replication - Server Settings
#synchronous_standby_names = '' # standby servers that provide sync rep #synchronous_standby_names = '' # standby servers that provide sync rep
......
...@@ -52,8 +52,15 @@ extern bool XactReadOnly; ...@@ -52,8 +52,15 @@ extern bool XactReadOnly;
extern bool DefaultXactDeferrable; extern bool DefaultXactDeferrable;
extern bool XactDeferrable; extern bool XactDeferrable;
/* Asynchronous commits */ typedef enum
extern bool XactSyncCommit; {
SYNCHRONOUS_COMMIT_OFF, /* asynchronous commit */
SYNCHRONOUS_COMMIT_LOCAL, /* wait for only local flush */
SYNCHRONOUS_COMMIT_ON /* wait for local flush and sync rep */
} SyncCommitLevel;
/* Synchronous commit level */
extern int synchronous_commit;
/* Kluge for 2PC support */ /* Kluge for 2PC support */
extern bool MyXactAccessedTempRel; extern bool MyXactAccessedTempRel;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "utils/guc.h" #include "utils/guc.h"
#define SyncRepRequested() \ #define SyncRepRequested() \
(synchronous_replication && max_wal_senders > 0) (max_wal_senders > 0 && synchronous_commit == SYNCHRONOUS_COMMIT_ON)
/* syncRepState */ /* syncRepState */
#define SYNC_REP_NOT_WAITING 0 #define SYNC_REP_NOT_WAITING 0
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#define SYNC_REP_WAIT_COMPLETE 2 #define SYNC_REP_WAIT_COMPLETE 2
/* user-settable parameters for synchronous replication */ /* user-settable parameters for synchronous replication */
extern bool synchronous_replication;
extern char *SyncRepStandbyNames; extern char *SyncRepStandbyNames;
/* called by user backend */ /* called by user backend */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment