Commit
de76884 changed an archive recovery so that the last WAL
segment with old timeline was renamed with suffix .partial. It should
have updated WAL-related utilities so that they can handle such
.paritial WAL files, but we forgot that.
This patch changes pg_archivecleanup so that it can clean up even
archived WAL files with .partial suffix. Also it allows us to specify
.partial WAL file name as the command-line argument "oldestkeptwalfile".
This patch also changes pg_resetxlog so that it can remove .partial
WAL files in pg_xlog directory.
pg_xlogdump cannot handle .partial WAL files. Per discussion,
we decided only to document that limitation instead of adding the fix.
Because a user can easily work around the limitation (i.e., just remove
.partial suffix from the file name) and the fix seems complicated for
very narrow use case.
Back-patch to 9.5 where the problem existed.
Review by Michael Paquier.
Discussion: http://www.postgresql.org/message-id/CAHGQGwGxMKnVHGgTfiig2Bt_2djec0in3-DLJmtg7+nEiidFdQ@mail.gmail.com
Only the specified timeline is displayed (or the default, if none is
specified). Records in other timelines are ignored.
</para>
+
+ <para>
+ <application>pg_xlogdump</> cannot read WAL files with suffix
+ <literal>.partial</>. If those files need to be read, <literal>.partial</>
+ suffix needs to be removed from the filename.
+ </para>
</refsect1>
<refsect1>
<para>
When used as a standalone program all WAL files logically preceding the
<replaceable>oldestkeptwalfile</> will be removed from <replaceable>archivelocation</>.
- In this mode, if you specify a <filename>.backup</> file name, then only the file prefix
- will be used as the <replaceable>oldestkeptwalfile</>. This allows you to remove
+ In this mode, if you specify a <filename>.partial</> or <filename>.backup</>
+ file name, then only the file prefix will be used as the
+ <replaceable>oldestkeptwalfile</>. This treatment of <filename>.backup</>
+ file name allows you to remove
all WAL files archived prior to a specific base backup without error.
For example, the following example will remove all files older than
WAL file name <filename>000000010000003700000010</>:
* file. Note that this means files are not removed in the order
* they were originally written, in case this worries you.
*/
- if (IsXLogFileName(walfile) &&
+ if ((IsXLogFileName(walfile) || IsPartialXLogFileName(walfile)) &&
strcmp(walfile + 8, exclusiveCleanupFileName + 8) < 0)
{
/*
* SetWALFileNameForCleanup()
*
* Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need_cleanup
+ * and decide whether we need cleanup
*/
static void
SetWALFileNameForCleanup(void)
/*
* If restartWALFileName is a WAL file name then just use it directly. If
- * restartWALFileName is a .backup filename, make sure we use the prefix
- * of the filename, otherwise we will remove wrong files since
- * 000000010000000000000010.00000020.backup is after
+ * restartWALFileName is a .partial or .backup filename, make sure we use
+ * the prefix of the filename, otherwise we will remove wrong files since
+ * 000000010000000000000010.partial and
+ * 000000010000000000000010.00000020.backup are after
* 000000010000000000000010.
*/
if (IsXLogFileName(restartWALFileName))
strcpy(exclusiveCleanupFileName, restartWALFileName);
fnameOK = true;
}
+ else if (IsPartialXLogFileName(restartWALFileName))
+ {
+ int args;
+ uint32 tli = 1,
+ log = 0,
+ seg = 0;
+
+ args = sscanf(restartWALFileName, "%08X%08X%08X.partial",
+ &tli, &log, &seg);
+ if (args == 3)
+ {
+ fnameOK = true;
+
+ /*
+ * Use just the prefix of the filename, ignore everything after
+ * first period
+ */
+ XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
+ }
+ }
else if (IsBackupHistoryFileName(restartWALFileName))
{
int args;
while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
- if (IsXLogFileName(xlde->d_name))
+ if (IsXLogFileName(xlde->d_name) ||
+ IsPartialXLogFileName(xlde->d_name))
{
unsigned int tli,
log,
while (errno = 0, (xlde = readdir(xldir)) != NULL)
{
- if (IsXLogFileName(xlde->d_name))
+ if (IsXLogFileName(xlde->d_name) ||
+ IsPartialXLogFileName(xlde->d_name))
{
snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name);
if (unlink(path) < 0)
{
if (strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
(strcmp(xlde->d_name + XLOG_FNAME_LEN, ".ready") == 0 ||
- strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0))
+ strcmp(xlde->d_name + XLOG_FNAME_LEN, ".done") == 0 ||
+ strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 ||
+ strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0))
{
snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name);
if (unlink(path) < 0)