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

Lines changed: 11 additions & 2 deletions
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

Lines changed: 39 additions & 0 deletions
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

Lines changed: 20 additions & 2 deletions
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

Lines changed: 4 additions & 1 deletion
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

Lines changed: 28 additions & 9 deletions
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

Lines changed: 8 additions & 2 deletions
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

Lines changed: 11 additions & 10 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 11 additions & 2 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy