Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ffd3774

Browse files
committed
Add archive_mode='always' option.
In 'always' mode, the standby independently archives all files it receives from the primary. Original patch by Fujii Masao, docs and review by me.
1 parent f6d65f0 commit ffd3774

File tree

9 files changed

+133
-29
lines changed

9 files changed

+133
-29
lines changed

doc/src/sgml/config.sgml

+11-2
Original file line numberDiff line numberDiff line change
@@ -2521,7 +2521,7 @@ include_dir 'conf.d'
25212521

25222522
<variablelist>
25232523
<varlistentry id="guc-archive-mode" xreflabel="archive_mode">
2524-
<term><varname>archive_mode</varname> (<type>boolean</type>)
2524+
<term><varname>archive_mode</varname> (<type>enum</type>)
25252525
<indexterm>
25262526
<primary><varname>archive_mode</> configuration parameter</primary>
25272527
</indexterm>
@@ -2530,7 +2530,16 @@ include_dir 'conf.d'
25302530
<para>
25312531
When <varname>archive_mode</> is enabled, completed WAL segments
25322532
are sent to archive storage by setting
2533-
<xref linkend="guc-archive-command">.
2533+
<xref linkend="guc-archive-command">. In addition to <literal>off</>,
2534+
to disable, there are two modes: <literal>on</>, and
2535+
<literal>always</>. During normal operation, there is no
2536+
difference between the two modes, but when set to <literal>always</>
2537+
the WAL archiver is enabled also during archive recovery or standby
2538+
mode. In <literal>always</> mode, all files restored from the archive
2539+
or streamed with streaming replication will be archived (again). See
2540+
<xref linkend="continuous-archiving-in-standby"> for details.
2541+
</para>
2542+
<para>
25342543
<varname>archive_mode</> and <varname>archive_command</> are
25352544
separate variables so that <varname>archive_command</> can be
25362545
changed without leaving archiving mode.

doc/src/sgml/high-availability.sgml

+39
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,45 @@ primary_slot_name = 'node_a_slot'
12201220

12211221
</sect3>
12221222
</sect2>
1223+
1224+
<sect2 id="continuous-archiving-in-standby">
1225+
<title>Continuous archiving in standby</title>
1226+
1227+
<indexterm>
1228+
<primary>continuous archiving</primary>
1229+
<secondary>in standby</secondary>
1230+
</indexterm>
1231+
1232+
<para>
1233+
When continuous WAL archiving is used in a standby, there are two
1234+
different scenarios: the WAL archive can be shared between the primary
1235+
and the standby, or the standby can have its own WAL archive. When
1236+
the standby has its own WAL archive, set <varname>archive_mode</varname>
1237+
to <literal>always</literal>, and the standby will call the archive
1238+
command for every WAL segment it receives, whether it's by restoring
1239+
from the archive or by streaming replication. The shared archive can
1240+
be handled similarly, but the archive_command must test if the file
1241+
being archived exists already, and if the existing file has identical
1242+
contents. This requires more care in the archive_command, as it must
1243+
be careful to not overwrite an existing file with different contents,
1244+
but return success if the exactly same file is archived twice. And
1245+
all that must be done free of race conditions, if two servers attempt
1246+
to archive the same file at the same time.
1247+
</para>
1248+
1249+
</para>
1250+
If <varname>archive_mode</varname> is set to <literal>on</>, the
1251+
archiver is not enabled during recovery or standby mode. If the standby
1252+
server is promoted, it will start archiving after the promotion, but
1253+
will not archive any WAL it did not generate itself. To get a complete
1254+
series of WAL files in the archive, you must ensure that all WAL is
1255+
archived, before it reaches the standby. This is inherently true with
1256+
file-based log shipping, as the standby can only restore files that
1257+
are found in the archive, but not if streaming replication is enabled.
1258+
When a server is not in recovery mode, there is no difference between
1259+
<literal>on</literal> and <literal>always</literal> modes.
1260+
</para>
1261+
</sect2>
12231262
</sect1>
12241263

12251264
<sect1 id="warm-standby-failover">

src/backend/access/transam/xlog.c

+20-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ int min_wal_size = 5; /* 80 MB */
8686
int wal_keep_segments = 0;
8787
int XLOGbuffers = -1;
8888
int XLogArchiveTimeout = 0;
89-
bool XLogArchiveMode = false;
89+
int XLogArchiveMode = ARCHIVE_MODE_OFF;
9090
char *XLogArchiveCommand = NULL;
9191
bool EnableHotStandby = false;
9292
bool fullPageWrites = true;
@@ -140,6 +140,24 @@ const struct config_enum_entry sync_method_options[] = {
140140
{NULL, 0, false}
141141
};
142142

143+
144+
/*
145+
* Although only "on", "off", and "always" are documented,
146+
* we accept all the likely variants of "on" and "off".
147+
*/
148+
const struct config_enum_entry archive_mode_options[] = {
149+
{"always", ARCHIVE_MODE_ALWAYS, false},
150+
{"on", ARCHIVE_MODE_ON, false},
151+
{"off", ARCHIVE_MODE_OFF, false},
152+
{"true", ARCHIVE_MODE_ON, true},
153+
{"false", ARCHIVE_MODE_OFF, true},
154+
{"yes", ARCHIVE_MODE_ON, true},
155+
{"no", ARCHIVE_MODE_OFF, true},
156+
{"1", ARCHIVE_MODE_ON, true},
157+
{"0", ARCHIVE_MODE_OFF, true},
158+
{NULL, 0, false}
159+
};
160+
143161
/*
144162
* Statistics for current checkpoint are collected in this global struct.
145163
* Because only the checkpointer or a stand-alone backend can perform
@@ -767,7 +785,7 @@ static MemoryContext walDebugCxt = NULL;
767785
#endif
768786

769787
static void readRecoveryCommandFile(void);
770-
static void exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo);
788+
static void exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog);
771789
static bool recoveryStopsBefore(XLogReaderState *record);
772790
static bool recoveryStopsAfter(XLogReaderState *record);
773791
static void recoveryPausesHere(void);

src/backend/access/transam/xlogarchive.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,10 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname)
480480
* Create .done file forcibly to prevent the restored segment from being
481481
* archived again later.
482482
*/
483-
XLogArchiveForceDone(xlogfname);
483+
if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
484+
XLogArchiveForceDone(xlogfname);
485+
else
486+
XLogArchiveNotify(xlogfname);
484487

485488
/*
486489
* If the existing file was replaced, since walsenders might have it open,

src/backend/postmaster/postmaster.c

+28-9
Original file line numberDiff line numberDiff line change
@@ -828,9 +828,9 @@ PostmasterMain(int argc, char *argv[])
828828
write_stderr("%s: max_wal_senders must be less than max_connections\n", progname);
829829
ExitPostmaster(1);
830830
}
831-
if (XLogArchiveMode && wal_level == WAL_LEVEL_MINIMAL)
831+
if (XLogArchiveMode > ARCHIVE_MODE_OFF && wal_level == WAL_LEVEL_MINIMAL)
832832
ereport(ERROR,
833-
(errmsg("WAL archival (archive_mode=on) requires wal_level \"archive\", \"hot_standby\", or \"logical\"")));
833+
(errmsg("WAL archival cannot be enabled when wal_level is \"minimal\"")));
834834
if (max_wal_senders > 0 && wal_level == WAL_LEVEL_MINIMAL)
835835
ereport(ERROR,
836836
(errmsg("WAL streaming (max_wal_senders > 0) requires wal_level \"archive\", \"hot_standby\", or \"logical\"")));
@@ -1645,13 +1645,21 @@ ServerLoop(void)
16451645
start_autovac_launcher = false; /* signal processed */
16461646
}
16471647

1648-
/* If we have lost the archiver, try to start a new one */
1649-
if (XLogArchivingActive() && PgArchPID == 0 && pmState == PM_RUN)
1650-
PgArchPID = pgarch_start();
1651-
1652-
/* If we have lost the stats collector, try to start a new one */
1653-
if (PgStatPID == 0 && pmState == PM_RUN)
1654-
PgStatPID = pgstat_start();
1648+
/*
1649+
* If we have lost the archiver, try to start a new one.
1650+
*
1651+
* If WAL archiving is enabled always, we try to start a new archiver
1652+
* even during recovery.
1653+
*/
1654+
if (PgArchPID == 0 && wal_level >= WAL_LEVEL_ARCHIVE)
1655+
{
1656+
if ((pmState == PM_RUN && XLogArchiveMode > ARCHIVE_MODE_OFF) ||
1657+
((pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY) &&
1658+
XLogArchiveMode == ARCHIVE_MODE_ALWAYS))
1659+
{
1660+
PgArchPID = pgarch_start();
1661+
}
1662+
}
16551663

16561664
/* If we need to signal the autovacuum launcher, do so now */
16571665
if (avlauncher_needs_signal)
@@ -4807,6 +4815,17 @@ sigusr1_handler(SIGNAL_ARGS)
48074815
Assert(BgWriterPID == 0);
48084816
BgWriterPID = StartBackgroundWriter();
48094817

4818+
/*
4819+
* Start the archiver if we're responsible for (re-)archiving received
4820+
* files.
4821+
*/
4822+
Assert(PgArchPID == 0);
4823+
if (wal_level >= WAL_LEVEL_ARCHIVE &&
4824+
XLogArchiveMode == ARCHIVE_MODE_ALWAYS)
4825+
{
4826+
PgArchPID = pgarch_start();
4827+
}
4828+
48104829
pmState = PM_RECOVERY;
48114830
}
48124831
if (CheckPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY) &&

src/backend/replication/walreceiver.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,10 @@ WalReceiverMain(void)
540540
* being archived later.
541541
*/
542542
XLogFileName(xlogfname, recvFileTLI, recvSegNo);
543-
XLogArchiveForceDone(xlogfname);
543+
if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
544+
XLogArchiveForceDone(xlogfname);
545+
else
546+
XLogArchiveNotify(xlogfname);
544547
}
545548
recvFile = -1;
546549

@@ -897,7 +900,10 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
897900
* from being archived later.
898901
*/
899902
XLogFileName(xlogfname, recvFileTLI, recvSegNo);
900-
XLogArchiveForceDone(xlogfname);
903+
if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
904+
XLogArchiveForceDone(xlogfname);
905+
else
906+
XLogArchiveNotify(xlogfname);
901907
}
902908
recvFile = -1;
903909

src/backend/utils/misc/guc.c

+11-10
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ static const struct config_enum_entry row_security_options[] = {
396396
* Options for enum values stored in other modules
397397
*/
398398
extern const struct config_enum_entry wal_level_options[];
399+
extern const struct config_enum_entry archive_mode_options[];
399400
extern const struct config_enum_entry sync_method_options[];
400401
extern const struct config_enum_entry dynamic_shared_memory_options[];
401402

@@ -1529,16 +1530,6 @@ static struct config_bool ConfigureNamesBool[] =
15291530
NULL, NULL, NULL
15301531
},
15311532

1532-
{
1533-
{"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
1534-
gettext_noop("Allows archiving of WAL files using archive_command."),
1535-
NULL
1536-
},
1537-
&XLogArchiveMode,
1538-
false,
1539-
NULL, NULL, NULL
1540-
},
1541-
15421533
{
15431534
{"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
15441535
gettext_noop("Allows connections and queries during recovery."),
@@ -3551,6 +3542,16 @@ static struct config_enum ConfigureNamesEnum[] =
35513542
NULL, assign_synchronous_commit, NULL
35523543
},
35533544

3545+
{
3546+
{"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
3547+
gettext_noop("Allows archiving of WAL files using archive_command."),
3548+
NULL
3549+
},
3550+
&XLogArchiveMode,
3551+
ARCHIVE_MODE_OFF, archive_mode_options,
3552+
NULL, NULL, NULL
3553+
},
3554+
35543555
{
35553556
{"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
35563557
gettext_noop("Enables logging of recovery-related debugging information."),

src/backend/utils/misc/postgresql.conf.sample

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206

207207
# - Archiving -
208208

209-
#archive_mode = off # allows archiving to be done
209+
#archive_mode = off # enables archiving; off, on, or always
210210
# (change requires restart)
211211
#archive_command = '' # command to use to archive a logfile segment
212212
# placeholders: %p = path of file to archive

src/include/access/xlog.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ extern int wal_keep_segments;
9898
extern int XLOGbuffers;
9999
extern int XLogArchiveTimeout;
100100
extern int wal_retrieve_retry_interval;
101-
extern bool XLogArchiveMode;
102101
extern char *XLogArchiveCommand;
103102
extern bool EnableHotStandby;
104103
extern bool fullPageWrites;
@@ -108,6 +107,15 @@ extern bool log_checkpoints;
108107

109108
extern int CheckPointSegments;
110109

110+
/* Archive modes */
111+
typedef enum ArchiveMode
112+
{
113+
ARCHIVE_MODE_OFF = 0, /* disabled */
114+
ARCHIVE_MODE_ON, /* enabled while server is running normally */
115+
ARCHIVE_MODE_ALWAYS /* enabled always (even during recovery) */
116+
} ArchiveMode;
117+
extern int XLogArchiveMode;
118+
111119
/* WAL levels */
112120
typedef enum WalLevel
113121
{
@@ -118,7 +126,8 @@ typedef enum WalLevel
118126
} WalLevel;
119127
extern int wal_level;
120128

121-
#define XLogArchivingActive() (XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
129+
#define XLogArchivingActive() \
130+
(XLogArchiveMode > ARCHIVE_MODE_OFF && wal_level >= WAL_LEVEL_ARCHIVE)
122131
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
123132

124133
/*

0 commit comments

Comments
 (0)