diff options
author | Bruce Momjian <bruce@momjian.us> | 2008-04-05 01:34:06 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2008-04-05 01:34:06 +0000 |
commit | 2a1cf97c22933368c8747711da0f30c35f4bddcd (patch) | |
tree | 59279eadb6955d135c10429f5843a6d71cc85f75 /src/backend/access | |
parent | a0fad9762a22e739de69c85b51ff7a47e672732f (diff) | |
download | postgresql-2a1cf97c22933368c8747711da0f30c35f4bddcd.tar.gz |
Have pg_stop_backup() wait for all archive files to be sent, rather than
returing right away. This guarantees that when pg_stop_backup()
returns, you have a valid backup.
Simon Riggs
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/transam/xlog.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 1b6a58f661..b059e49bc3 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.295 2008/03/25 22:42:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.296 2008/04/05 01:34:06 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -382,7 +382,7 @@ static bool InRedo = false; static void XLogArchiveNotify(const char *xlog); static void XLogArchiveNotifySeg(uint32 log, uint32 seg); -static bool XLogArchiveCheckDone(const char *xlog); +static bool XLogArchiveCheckDone(const char *xlog, bool create_if_missing); static void XLogArchiveCleanup(const char *xlog); static void readRecoveryCommandFile(void); static void exitArchiveRecovery(TimeLineID endTLI, @@ -1128,7 +1128,7 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg) * create <XLOG>.ready fails, we'll retry during subsequent checkpoints. */ static bool -XLogArchiveCheckDone(const char *xlog) +XLogArchiveCheckDone(const char *xlog, bool create_if_missing) { char archiveStatusPath[MAXPGPATH]; struct stat stat_buf; @@ -1153,7 +1153,9 @@ XLogArchiveCheckDone(const char *xlog) return true; /* Retry creation of the .ready file */ - XLogArchiveNotify(xlog); + if (create_if_missing) + XLogArchiveNotify(xlog); + return false; } @@ -2704,7 +2706,7 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr) strspn(xlde->d_name, "0123456789ABCDEF") == 24 && strcmp(xlde->d_name + 8, lastoff + 8) <= 0) { - if (XLogArchiveCheckDone(xlde->d_name)) + if (XLogArchiveCheckDone(xlde->d_name, true)) { snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name); @@ -2771,7 +2773,7 @@ CleanupBackupHistory(void) strcmp(xlde->d_name + strlen(xlde->d_name) - strlen(".backup"), ".backup") == 0) { - if (XLogArchiveCheckDone(xlde->d_name)) + if (XLogArchiveCheckDone(xlde->d_name, true)) { ereport(DEBUG2, (errmsg("removing transaction log backup history file \"%s\"", @@ -6556,6 +6558,8 @@ pg_stop_backup(PG_FUNCTION_ARGS) FILE *fp; char ch; int ich; + int seconds_before_warning; + int waits = 0; if (!superuser()) ereport(ERROR, @@ -6660,6 +6664,39 @@ pg_stop_backup(PG_FUNCTION_ARGS) CleanupBackupHistory(); /* + * Wait until the history file has been archived. We assume that the + * alphabetic sorting property of the WAL files ensures the last WAL + * file is guaranteed archived by the time the history file is archived. + * + * We wait forever, since archive_command is supposed to work and + * we assume the admin wanted his backup to work completely. If you + * don't wish to wait, you can SET statement_timeout = xx; + * + * If the status file is missing, we assume that is because it was + * set to .ready before we slept, then while asleep it has been set + * to .done and then removed by a concurrent checkpoint. + */ + BackupHistoryFileName(histfilepath, ThisTimeLineID, _logId, _logSeg, + startpoint.xrecoff % XLogSegSize); + + seconds_before_warning = 60; + waits = 0; + + while (!XLogArchiveCheckDone(histfilepath, false)) + { + CHECK_FOR_INTERRUPTS(); + + pg_usleep(1000000L); + + if (++waits >= seconds_before_warning) + { + seconds_before_warning *= 2; /* This wraps in >10 years... */ + elog(WARNING, "pg_stop_backup() waiting for archive to complete " + "(%d seconds delay)", waits); + } + } + + /* * We're done. As a convenience, return the ending WAL location. */ snprintf(stopxlogfilename, sizeof(stopxlogfilename), "%X/%X", |