mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
pg_stop_backup was calling XLogArchiveNotify() twice for the newly created
backup history file. Bug introduced by the 8.1 change to make pg_stop_backup delete older history files. Per report from Masao Fujii.
This commit is contained in:
parent
39bed3b388
commit
3a04f53e7f
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.240 2006/06/18 18:30:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.241 2006/06/22 20:42:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -460,7 +460,7 @@ static bool InRedo = false;
|
|||||||
|
|
||||||
static void XLogArchiveNotify(const char *xlog);
|
static void XLogArchiveNotify(const char *xlog);
|
||||||
static void XLogArchiveNotifySeg(uint32 log, uint32 seg);
|
static void XLogArchiveNotifySeg(uint32 log, uint32 seg);
|
||||||
static bool XLogArchiveIsDone(const char *xlog);
|
static bool XLogArchiveCheckDone(const char *xlog);
|
||||||
static void XLogArchiveCleanup(const char *xlog);
|
static void XLogArchiveCleanup(const char *xlog);
|
||||||
static void readRecoveryCommandFile(void);
|
static void readRecoveryCommandFile(void);
|
||||||
static void exitArchiveRecovery(TimeLineID endTLI,
|
static void exitArchiveRecovery(TimeLineID endTLI,
|
||||||
@ -484,7 +484,7 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname,
|
|||||||
static int PreallocXlogFiles(XLogRecPtr endptr);
|
static int PreallocXlogFiles(XLogRecPtr endptr);
|
||||||
static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
|
static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
|
||||||
int *nsegsremoved, int *nsegsrecycled);
|
int *nsegsremoved, int *nsegsrecycled);
|
||||||
static void RemoveOldBackupHistory(void);
|
static void CleanupBackupHistory(void);
|
||||||
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode);
|
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode);
|
||||||
static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
|
static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);
|
||||||
static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt);
|
static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt);
|
||||||
@ -1109,24 +1109,30 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XLogArchiveIsDone
|
* XLogArchiveCheckDone
|
||||||
*
|
*
|
||||||
* Checks for a ".done" archive notification file. This is called when we
|
* This is called when we are ready to delete or recycle an old XLOG segment
|
||||||
* are ready to delete or recycle an old XLOG segment file. If it is okay
|
* file or backup history file. If it is okay to delete it then return true.
|
||||||
* to delete it then return true.
|
* If it is not time to delete it, make sure a .ready file exists, and return
|
||||||
|
* false.
|
||||||
*
|
*
|
||||||
* If <XLOG>.done exists, then return true; else if <XLOG>.ready exists,
|
* If <XLOG>.done exists, then return true; else if <XLOG>.ready exists,
|
||||||
* then return false; else create <XLOG>.ready and return false. The
|
* then return false; else create <XLOG>.ready and return false.
|
||||||
* last case covers the possibility that the original attempt to create
|
*
|
||||||
* <XLOG>.ready failed.
|
* The reason we do things this way is so that if the original attempt to
|
||||||
|
* create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
XLogArchiveIsDone(const char *xlog)
|
XLogArchiveCheckDone(const char *xlog)
|
||||||
{
|
{
|
||||||
char archiveStatusPath[MAXPGPATH];
|
char archiveStatusPath[MAXPGPATH];
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
|
|
||||||
/* First check for .done --- this is the expected case */
|
/* Always deletable if archiving is off */
|
||||||
|
if (!XLogArchivingActive())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* First check for .done --- this means archiver is done with it */
|
||||||
StatusFilePath(archiveStatusPath, xlog, ".done");
|
StatusFilePath(archiveStatusPath, xlog, ".done");
|
||||||
if (stat(archiveStatusPath, &stat_buf) == 0)
|
if (stat(archiveStatusPath, &stat_buf) == 0)
|
||||||
return true;
|
return true;
|
||||||
@ -2438,14 +2444,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
|
|||||||
strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
|
strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
|
||||||
strcmp(xlde->d_name + 8, lastoff + 8) <= 0)
|
strcmp(xlde->d_name + 8, lastoff + 8) <= 0)
|
||||||
{
|
{
|
||||||
bool recycle;
|
if (XLogArchiveCheckDone(xlde->d_name))
|
||||||
|
|
||||||
if (XLogArchivingActive())
|
|
||||||
recycle = XLogArchiveIsDone(xlde->d_name);
|
|
||||||
else
|
|
||||||
recycle = true;
|
|
||||||
|
|
||||||
if (recycle)
|
|
||||||
{
|
{
|
||||||
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
|
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name);
|
||||||
|
|
||||||
@ -2487,10 +2486,12 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove previous backup history files
|
* Remove previous backup history files. This also retries creation of
|
||||||
|
* .ready files for any backup history files for which XLogArchiveNotify
|
||||||
|
* failed earlier.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
RemoveOldBackupHistory(void)
|
CleanupBackupHistory(void)
|
||||||
{
|
{
|
||||||
DIR *xldir;
|
DIR *xldir;
|
||||||
struct dirent *xlde;
|
struct dirent *xlde;
|
||||||
@ -2510,8 +2511,7 @@ RemoveOldBackupHistory(void)
|
|||||||
strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"),
|
strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"),
|
||||||
".backup") == 0)
|
".backup") == 0)
|
||||||
{
|
{
|
||||||
/* Remove any *.backup files that have been archived. */
|
if (XLogArchiveCheckDone(xlde->d_name))
|
||||||
if (!XLogArchivingActive() || XLogArchiveIsDone(xlde->d_name))
|
|
||||||
{
|
{
|
||||||
ereport(DEBUG2,
|
ereport(DEBUG2,
|
||||||
(errmsg("removing transaction log backup history file \"%s\"",
|
(errmsg("removing transaction log backup history file \"%s\"",
|
||||||
@ -5968,17 +5968,12 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
|||||||
errmsg("could not remove file \"%s\": %m",
|
errmsg("could not remove file \"%s\": %m",
|
||||||
BACKUP_LABEL_FILE)));
|
BACKUP_LABEL_FILE)));
|
||||||
|
|
||||||
RemoveOldBackupHistory();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify archiver that history file may be archived immediately
|
* Clean out any no-longer-needed history files. As a side effect,
|
||||||
|
* this will post a .ready file for the newly created history file,
|
||||||
|
* notifying the archiver that history file may be archived immediately.
|
||||||
*/
|
*/
|
||||||
if (XLogArchivingActive())
|
CleanupBackupHistory();
|
||||||
{
|
|
||||||
BackupHistoryFileName(histfilepath, ThisTimeLineID, _logId, _logSeg,
|
|
||||||
startpoint.xrecoff % XLogSegSize);
|
|
||||||
XLogArchiveNotify(histfilepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're done. As a convenience, return the ending WAL offset.
|
* We're done. As a convenience, return the ending WAL offset.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user