From 66d3e97e2685a1b62f91e628eb6726993c034956 Mon Sep 17 00:00:00 2001 From: Arthur Zakirov Date: Mon, 22 May 2017 14:22:20 +0300 Subject: [PATCH] Do non-exclusive backup for PostgreSQL 9.6+ --- backup.c | 56 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/backup.c b/backup.c index 2ccdd728..70d5d791 100644 --- a/backup.c +++ b/backup.c @@ -53,6 +53,13 @@ static int is_ptrack_enable = false; /* Backup connection */ static PGconn *backup_conn = NULL; +/* PostgreSQL server version from "backup_conn" */ +static int server_version = 0; + +static bool exclusive_backup = false; +/* Is pg_start_backup() was executed */ +static bool backup_in_progress = false; + typedef struct { const char *from_root; @@ -159,7 +166,7 @@ do_backup_database(parray *backup_list) * If backup_label does not exist in $PGDATA, stop taking backup. * NOTE. We can check it only on master, though. */ - if(!from_replica) + if (exclusive_backup) { char label_path[MAXPGPATH]; join_path_components(label_path, pgdata, PG_BACKUP_LABEL_FILE); @@ -399,13 +406,15 @@ do_backup(void) backup_conn = pgut_connect(pgut_dbname); pgut_atexit_push(backup_disconnect, NULL); - /* Confirm that this server version is supported */ - check_server_version(); /* Confirm data block size and xlog block size are compatible */ confirm_block_size("block_size", BLCKSZ); confirm_block_size("wal_block_size", XLOG_BLCKSZ); from_replica = pg_is_in_recovery(); + + /* Confirm that this server version is supported */ + check_server_version(); + current.checksum_version = get_data_checksum_version(true); current.stream = stream_wal; @@ -489,7 +498,6 @@ do_backup(void) static void check_server_version(void) { - static int server_version = 0; /* confirm server version */ server_version = PQserverVersion(backup_conn); @@ -506,6 +514,9 @@ check_server_version(void) server_version / 10000, (server_version / 100) % 100, server_version % 100, "9.6"); + + /* Do exclusive backup only for PostgreSQL 9.5 */ + exclusive_backup = server_version < 90600; } /* @@ -581,7 +592,7 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup) /* 2nd argument is 'fast'*/ params[1] = smooth ? "false" : "true"; - if (from_replica) + if (!exclusive_backup) res = pgut_execute(backup_conn, "SELECT pg_start_backup($1, $2, false)", 2, @@ -592,6 +603,8 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup) 2, params); + backup_in_progress = true; + /* Extract timeline and LSN from results of pg_start_backup() */ XLogDataFromLSN(PQgetvalue(res, 0, 0), &xlogid, &xrecoff); /* Calculate LSN */ @@ -629,13 +642,13 @@ pg_switch_wal(void) NULL); PQclear(res); -#if PG_VERSION_NUM >= 100000 - res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_wal()", 0, - NULL); -#else - res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_xlog()", 0, - NULL); -#endif + if (server_version >= 100000) + res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_wal()", 0, + NULL); + else + res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_xlog()", 0, + NULL); + PQclear(res); } @@ -891,12 +904,15 @@ pg_stop_backup(pgBackup *backup) time_t recovery_time; TransactionId recovery_xid; + if (!backup_in_progress) + elog(FATAL, "backup is not in progress"); + /* Remove annoying NOTICE messages generated by backend */ res = pgut_execute(backup_conn, "SET client_min_messages = warning;", 0, NULL); PQclear(res); - if (from_replica) + if (!exclusive_backup) /* * Stop the non-exclusive backup. Besides stop_lsn it returns from * pg_stop_backup(false) copy of the backup label and tablespace map @@ -914,13 +930,15 @@ pg_stop_backup(pgBackup *backup) " FROM pg_stop_backup()", 0, NULL); + backup_in_progress = false; + /* Extract timeline and LSN from results of pg_stop_backup() */ XLogDataFromLSN(PQgetvalue(res, 0, 0), &xlogid, &xrecoff); /* Calculate LSN */ stop_backup_lsn = (XLogRecPtr) ((uint64) xlogid << 32) | xrecoff; /* Write backup_label and tablespace_map for backup from replica */ - if (from_replica) + if (!exclusive_backup) { char path[MAXPGPATH]; char backup_label[MAXPGPATH]; @@ -1081,8 +1099,6 @@ fileExists(const char *path) static void backup_cleanup(bool fatal, void *userdata) { - char path[MAXPGPATH]; - /* * Update status of backup in BACKUP_CONTROL_FILE to ERROR. * end_time != 0 means backup finished @@ -1096,13 +1112,11 @@ backup_cleanup(bool fatal, void *userdata) } /* - * If backup_label exists in $PGDATA, notify stop of backup to PostgreSQL - * TODO Do we need this? + * If backup is in progress, notify stop of backup to PostgreSQL */ - join_path_components(path, pgdata, PG_BACKUP_LABEL_FILE); - if (fileExists(path)) + if (backup_in_progress) { - elog(LOG, "%s exists, stop backup", PG_BACKUP_LABEL_FILE); + elog(LOG, "backup in progress, stop backup"); pg_stop_backup(NULL); /* don't care stop_lsn on error case */ } }