Skip to content

Commit 66d3e97

Browse files
committed
Do non-exclusive backup for PostgreSQL 9.6+
1 parent 7a294ad commit 66d3e97

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed

backup.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ static int is_ptrack_enable = false;
5353
/* Backup connection */
5454
static PGconn *backup_conn = NULL;
5555

56+
/* PostgreSQL server version from "backup_conn" */
57+
static int server_version = 0;
58+
59+
static bool exclusive_backup = false;
60+
/* Is pg_start_backup() was executed */
61+
static bool backup_in_progress = false;
62+
5663
typedef struct
5764
{
5865
const char *from_root;
@@ -159,7 +166,7 @@ do_backup_database(parray *backup_list)
159166
* If backup_label does not exist in $PGDATA, stop taking backup.
160167
* NOTE. We can check it only on master, though.
161168
*/
162-
if(!from_replica)
169+
if (exclusive_backup)
163170
{
164171
char label_path[MAXPGPATH];
165172
join_path_components(label_path, pgdata, PG_BACKUP_LABEL_FILE);
@@ -399,13 +406,15 @@ do_backup(void)
399406
backup_conn = pgut_connect(pgut_dbname);
400407
pgut_atexit_push(backup_disconnect, NULL);
401408

402-
/* Confirm that this server version is supported */
403-
check_server_version();
404409
/* Confirm data block size and xlog block size are compatible */
405410
confirm_block_size("block_size", BLCKSZ);
406411
confirm_block_size("wal_block_size", XLOG_BLCKSZ);
407412

408413
from_replica = pg_is_in_recovery();
414+
415+
/* Confirm that this server version is supported */
416+
check_server_version();
417+
409418
current.checksum_version = get_data_checksum_version(true);
410419
current.stream = stream_wal;
411420

@@ -489,7 +498,6 @@ do_backup(void)
489498
static void
490499
check_server_version(void)
491500
{
492-
static int server_version = 0;
493501
/* confirm server version */
494502
server_version = PQserverVersion(backup_conn);
495503

@@ -506,6 +514,9 @@ check_server_version(void)
506514
server_version / 10000,
507515
(server_version / 100) % 100,
508516
server_version % 100, "9.6");
517+
518+
/* Do exclusive backup only for PostgreSQL 9.5 */
519+
exclusive_backup = server_version < 90600;
509520
}
510521

511522
/*
@@ -581,7 +592,7 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
581592

582593
/* 2nd argument is 'fast'*/
583594
params[1] = smooth ? "false" : "true";
584-
if (from_replica)
595+
if (!exclusive_backup)
585596
res = pgut_execute(backup_conn,
586597
"SELECT pg_start_backup($1, $2, false)",
587598
2,
@@ -592,6 +603,8 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
592603
2,
593604
params);
594605

606+
backup_in_progress = true;
607+
595608
/* Extract timeline and LSN from results of pg_start_backup() */
596609
XLogDataFromLSN(PQgetvalue(res, 0, 0), &xlogid, &xrecoff);
597610
/* Calculate LSN */
@@ -629,13 +642,13 @@ pg_switch_wal(void)
629642
NULL);
630643
PQclear(res);
631644

632-
#if PG_VERSION_NUM >= 100000
633-
res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_wal()", 0,
634-
NULL);
635-
#else
636-
res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_xlog()", 0,
637-
NULL);
638-
#endif
645+
if (server_version >= 100000)
646+
res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_wal()", 0,
647+
NULL);
648+
else
649+
res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_xlog()", 0,
650+
NULL);
651+
639652
PQclear(res);
640653
}
641654

@@ -891,12 +904,15 @@ pg_stop_backup(pgBackup *backup)
891904
time_t recovery_time;
892905
TransactionId recovery_xid;
893906

907+
if (!backup_in_progress)
908+
elog(FATAL, "backup is not in progress");
909+
894910
/* Remove annoying NOTICE messages generated by backend */
895911
res = pgut_execute(backup_conn, "SET client_min_messages = warning;",
896912
0, NULL);
897913
PQclear(res);
898914

899-
if (from_replica)
915+
if (!exclusive_backup)
900916
/*
901917
* Stop the non-exclusive backup. Besides stop_lsn it returns from
902918
* pg_stop_backup(false) copy of the backup label and tablespace map
@@ -914,13 +930,15 @@ pg_stop_backup(pgBackup *backup)
914930
" FROM pg_stop_backup()",
915931
0, NULL);
916932

933+
backup_in_progress = false;
934+
917935
/* Extract timeline and LSN from results of pg_stop_backup() */
918936
XLogDataFromLSN(PQgetvalue(res, 0, 0), &xlogid, &xrecoff);
919937
/* Calculate LSN */
920938
stop_backup_lsn = (XLogRecPtr) ((uint64) xlogid << 32) | xrecoff;
921939

922940
/* Write backup_label and tablespace_map for backup from replica */
923-
if (from_replica)
941+
if (!exclusive_backup)
924942
{
925943
char path[MAXPGPATH];
926944
char backup_label[MAXPGPATH];
@@ -1081,8 +1099,6 @@ fileExists(const char *path)
10811099
static void
10821100
backup_cleanup(bool fatal, void *userdata)
10831101
{
1084-
char path[MAXPGPATH];
1085-
10861102
/*
10871103
* Update status of backup in BACKUP_CONTROL_FILE to ERROR.
10881104
* end_time != 0 means backup finished
@@ -1096,13 +1112,11 @@ backup_cleanup(bool fatal, void *userdata)
10961112
}
10971113

10981114
/*
1099-
* If backup_label exists in $PGDATA, notify stop of backup to PostgreSQL
1100-
* TODO Do we need this?
1115+
* If backup is in progress, notify stop of backup to PostgreSQL
11011116
*/
1102-
join_path_components(path, pgdata, PG_BACKUP_LABEL_FILE);
1103-
if (fileExists(path))
1117+
if (backup_in_progress)
11041118
{
1105-
elog(LOG, "%s exists, stop backup", PG_BACKUP_LABEL_FILE);
1119+
elog(LOG, "backup in progress, stop backup");
11061120
pg_stop_backup(NULL); /* don't care stop_lsn on error case */
11071121
}
11081122
}

0 commit comments

Comments
 (0)