Skip to content

Commit b314856

Browse files
author
Artur Zakirov
committed
Read recovery_time and recovery_xid from WAL segments whenever possible
1 parent 62953a7 commit b314856

File tree

9 files changed

+173
-130
lines changed

9 files changed

+173
-130
lines changed

backup.c

Lines changed: 54 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ static parray *do_backup_database(parray *backup_list, bool smooth_checkpoint);
6767

6868
static void pg_start_backup(const char *label, bool smooth, pgBackup *backup);
6969
static void pg_stop_backup(pgBackup *backup);
70-
static void pg_switch_xlog(void);
7170

7271
static bool pg_is_standby(void);
7372
static void add_pgdata_files(parray *files, const char *root);
@@ -169,7 +168,7 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
169168
/* start stream replication */
170169
if (stream_wal)
171170
{
172-
join_path_components(dst_backup_path, database_path, "pg_xlog");
171+
join_path_components(dst_backup_path, database_path, PG_XLOG_DIR);
173172
dir_create_dir(dst_backup_path, DIR_PERMISSION);
174173

175174
pthread_mutex_lock(&check_stream_mut);
@@ -186,14 +185,14 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
186185
char label_path[MAXPGPATH];
187186

188187
/* If backup_label does not exist in $PGDATA, stop taking backup */
189-
join_path_components(label_path, pgdata, "backup_label");
188+
join_path_components(label_path, pgdata, PG_BACKUP_LABEL_FILE);
190189

191190
/* Leave if no backup file */
192191
if (!fileExists(label_path))
193192
{
194-
elog(LOG, "backup_label does not exist, stopping backup");
193+
elog(LOG, "%s does not exist, stopping backup", PG_BACKUP_LABEL_FILE);
195194
pg_stop_backup(NULL);
196-
elog(ERROR, "backup_label does not exist in PGDATA.");
195+
elog(ERROR, "%s does not exist in PGDATA", PG_BACKUP_LABEL_FILE);
197196
}
198197
}
199198

@@ -353,7 +352,7 @@ do_backup_database(parray *backup_list, bool smooth_checkpoint)
353352

354353
/* Scan backup pg_xlog dir */
355354
list_file = parray_new();
356-
join_path_components(pg_xlog_path, database_path, "pg_xlog");
355+
join_path_components(pg_xlog_path, database_path, PG_XLOG_DIR);
357356
dir_list_file(list_file, pg_xlog_path, false, true, false);
358357

359358
/* Remove file path root prefix and calc meta */
@@ -739,6 +738,8 @@ wait_archive_lsn(XLogRecPtr lsn, bool prev_segno)
739738
char wal_file[MAXFNAMELEN];
740739
uint32 try_count = 0;
741740

741+
Assert(!stream_wal);
742+
742743
tli = get_current_timeline(false);
743744

744745
/* As well as WAL file name */
@@ -764,8 +765,8 @@ wait_archive_lsn(XLogRecPtr lsn, bool prev_segno)
764765

765766
if (archive_timeout > 0 && try_count > archive_timeout)
766767
elog(ERROR,
767-
"switched WAL could not be archived in %d seconds",
768-
archive_timeout);
768+
"switched WAL segment %s could not be archived in %d seconds",
769+
wal_file, archive_timeout);
769770
}
770771
}
771772

@@ -778,6 +779,8 @@ pg_stop_backup(pgBackup *backup)
778779
PGresult *res;
779780
uint32 xlogid;
780781
uint32 xrecoff;
782+
time_t recovery_time;
783+
TransactionId recovery_xid;
781784

782785
/* Remove annoying NOTICE messages generated by backend */
783786
res = pgut_execute(backup_conn, "SET client_min_messages = warning;",
@@ -786,10 +789,18 @@ pg_stop_backup(pgBackup *backup)
786789

787790
if (from_replica)
788791
res = pgut_execute(backup_conn,
789-
"SELECT * FROM pg_stop_backup(false)", 0, NULL);
792+
"SELECT *, txid_snapshot_xmax(txid_current_snapshot()) FROM pg_stop_backup(false)",
793+
0, NULL);
790794
else
791795
res = pgut_execute(backup_conn,
792-
"SELECT * FROM pg_stop_backup()", 0, NULL);
796+
"SELECT *, txid_snapshot_xmax(txid_current_snapshot()) FROM pg_stop_backup()",
797+
0, NULL);
798+
799+
/*
800+
* We will use this value if there are no transactions between start_lsn
801+
* and stop_lsn.
802+
*/
803+
recovery_time = time(NULL);
793804

794805
/*
795806
* Extract timeline and LSN from results of pg_stop_backup()
@@ -809,7 +820,7 @@ pg_stop_backup(pgBackup *backup)
809820
Assert(PQnfields(res) >= 3);
810821

811822
pgBackupGetPath(&current, path, lengthof(path), DATABASE_DIR);
812-
join_path_components(backup_label, path, "backup_label");
823+
join_path_components(backup_label, path, PG_BACKUP_LABEL_FILE);
813824

814825
/* Write backup_label */
815826
fp = fopen(backup_label, "w");
@@ -823,7 +834,7 @@ pg_stop_backup(pgBackup *backup)
823834
file = pgFileNew(backup_label, true);
824835
calc_file(file);
825836
free(file->path);
826-
file->path = strdup("backup_label");
837+
file->path = strdup(PG_BACKUP_LABEL_FILE);
827838
parray_append(backup_files_list, file);
828839

829840
/* Write tablespace_map */
@@ -847,7 +858,17 @@ pg_stop_backup(pgBackup *backup)
847858
file->path = strdup("tablespace_map");
848859
parray_append(backup_files_list, file);
849860
}
861+
862+
if (sscanf(PQgetvalue(res, 0, 3), XID_FMT, &recovery_xid) != 1)
863+
elog(ERROR,
864+
"result of txid_snapshot_xmax() is invalid: %s",
865+
PQerrorMessage(backup_conn));
850866
}
867+
else
868+
if (sscanf(PQgetvalue(res, 0, 1), XID_FMT, &recovery_xid) != 1)
869+
elog(ERROR,
870+
"result of txid_snapshot_xmax() is invalid: %s",
871+
PQerrorMessage(backup_conn));
851872

852873
PQclear(res);
853874

@@ -857,63 +878,30 @@ pg_stop_backup(pgBackup *backup)
857878
/* Fill in fields if backup exists */
858879
if (backup != NULL)
859880
{
860-
backup->tli = get_current_timeline(false);
861-
backup->stop_lsn = stop_backup_lsn;
881+
char *xlog_path,
882+
stream_xlog_path[MAXPGPATH];
862883

863-
if (from_replica)
864-
res = pgut_execute(backup_conn, TXID_CURRENT_IF_SQL, 0, NULL);
884+
if (stream_wal)
885+
{
886+
join_path_components(stream_xlog_path, pgdata, PG_XLOG_DIR);
887+
xlog_path = stream_xlog_path;
888+
}
865889
else
866-
res = pgut_execute(backup_conn, TXID_CURRENT_SQL, 0, NULL);
867-
868-
if (sscanf(PQgetvalue(res, 0, 0), XID_FMT, &backup->recovery_xid) != 1)
869-
elog(ERROR,
870-
"result of txid_current() is invalid: %s",
871-
PQerrorMessage(backup_conn));
872-
backup->recovery_time = time(NULL);
890+
xlog_path = arclog_path;
873891

874-
elog(LOG, "finish backup: tli=%X lsn=%X/%08X xid=%s",
875-
backup->tli,
876-
(uint32) (backup->stop_lsn >> 32), (uint32) backup->stop_lsn,
877-
PQgetvalue(res, 0, 0));
892+
backup->tli = get_current_timeline(false);
893+
backup->stop_lsn = stop_backup_lsn;
878894

879-
PQclear(res);
895+
if (!read_recovery_info(xlog_path, backup->tli,
896+
backup->start_lsn, backup->stop_lsn,
897+
&backup->recovery_time, &backup->recovery_xid))
898+
{
899+
backup->recovery_time = recovery_time;
900+
backup->recovery_xid = recovery_xid;
901+
}
880902
}
881903
}
882904

883-
/*
884-
* Switch to a new WAL segment for master.
885-
*/
886-
static void
887-
pg_switch_xlog(void)
888-
{
889-
PGresult *res;
890-
XLogRecPtr lsn;
891-
uint32 xlogid;
892-
uint32 xrecoff;
893-
894-
/* Remove annoying NOTICE messages generated by backend */
895-
res = pgut_execute(backup_conn, "SET client_min_messages = warning;", 0,
896-
NULL);
897-
PQclear(res);
898-
899-
res = pgut_execute(backup_conn, "SELECT * FROM pg_switch_xlog()",
900-
0, NULL);
901-
902-
/*
903-
* Extract timeline and LSN from results of pg_stop_backup()
904-
* and friends.
905-
*/
906-
XLogDataFromLSN(PQgetvalue(res, 0, 0), &xlogid, &xrecoff);
907-
/* Calculate LSN */
908-
lsn = (XLogRecPtr) ((uint64) xlogid << 32) | xrecoff;
909-
910-
PQclear(res);
911-
912-
/* Wait for returned lsn - 1 in archive folder */
913-
wait_archive_lsn(lsn, false);
914-
}
915-
916-
917905
/*
918906
* Check if node is a standby by looking at the presence of
919907
* recovery.conf.
@@ -957,11 +945,10 @@ backup_cleanup(bool fatal, void *userdata)
957945
return;
958946

959947
/* If backup_label exist in $PGDATA, notify stop of backup to PostgreSQL */
960-
snprintf(path, lengthof(path), "%s/backup_label", pgdata);
961-
make_native_path(path);
948+
join_path_components(path, pgdata, PG_BACKUP_LABEL_FILE);
962949
if (fileExists(path))
963950
{
964-
elog(LOG, "backup_label exists, stop backup");
951+
elog(LOG, "%s exists, stop backup", PG_BACKUP_LABEL_FILE);
965952
pg_stop_backup(NULL); /* don't care stop_lsn on error case */
966953
}
967954

@@ -1240,7 +1227,7 @@ add_pgdata_files(parray *files, const char *root)
12401227
relative = file->path + strlen(root) + 1;
12411228
if (!path_is_prefix_of_path("base", relative) &&
12421229
/*!path_is_prefix_of_path("global", relative) &&*/ //TODO What's wrong with this line?
1243-
!path_is_prefix_of_path("pg_tblspc", relative))
1230+
!path_is_prefix_of_path(PG_TBLSPC_DIR, relative))
12441231
continue;
12451232

12461233
/* Get file name from path */
@@ -1508,7 +1495,7 @@ make_pagemap_from_ptrack(parray *files)
15081495
}
15091496
/* For unix only now */
15101497
sscanf(tmp_path, "%u/%u_ptrack", &db_oid, &rel_oid);
1511-
tablespace = strstr(p->ptrack_path, "pg_tblspc");
1498+
tablespace = strstr(p->ptrack_path, PG_TBLSPC_DIR);
15121499
if (tablespace != NULL)
15131500
sscanf(tablespace+10, "%i/", &tablespace_oid);
15141501

dir.c

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,43 +27,43 @@
2727
*/
2828
const char *pgdata_exclude_dir[] =
2929
{
30-
"pg_xlog",
31-
/*
32-
* Skip temporary statistics files. PG_STAT_TMP_DIR must be skipped even
33-
* when stats_temp_directory is set because PGSS_TEXT_FILE is always created
34-
* there.
35-
*/
36-
"pg_stat_tmp",
37-
"pgsql_tmp",
38-
39-
/*
40-
* It is generally not useful to backup the contents of this directory even
41-
* if the intention is to restore to another master. See backup.sgml for a
42-
* more detailed description.
43-
*/
44-
"pg_replslot",
45-
46-
/* Contents removed on startup, see dsm_cleanup_for_mmap(). */
47-
"pg_dynshmem",
48-
49-
/* Contents removed on startup, see AsyncShmemInit(). */
50-
"pg_notify",
51-
52-
/*
53-
* Old contents are loaded for possible debugging but are not required for
54-
* normal operation, see OldSerXidInit().
55-
*/
56-
"pg_serial",
57-
58-
/* Contents removed on startup, see DeleteAllExportedSnapshotFiles(). */
59-
"pg_snapshots",
60-
61-
/* Contents zeroed on startup, see StartupSUBTRANS(). */
62-
"pg_subtrans",
63-
64-
/* end of list */
65-
NULL, /* pg_log will be set later */
66-
NULL
30+
PG_XLOG_DIR,
31+
/*
32+
* Skip temporary statistics files. PG_STAT_TMP_DIR must be skipped even
33+
* when stats_temp_directory is set because PGSS_TEXT_FILE is always created
34+
* there.
35+
*/
36+
"pg_stat_tmp",
37+
"pgsql_tmp",
38+
39+
/*
40+
* It is generally not useful to backup the contents of this directory even
41+
* if the intention is to restore to another master. See backup.sgml for a
42+
* more detailed description.
43+
*/
44+
"pg_replslot",
45+
46+
/* Contents removed on startup, see dsm_cleanup_for_mmap(). */
47+
"pg_dynshmem",
48+
49+
/* Contents removed on startup, see AsyncShmemInit(). */
50+
"pg_notify",
51+
52+
/*
53+
* Old contents are loaded for possible debugging but are not required for
54+
* normal operation, see OldSerXidInit().
55+
*/
56+
"pg_serial",
57+
58+
/* Contents removed on startup, see DeleteAllExportedSnapshotFiles(). */
59+
"pg_snapshots",
60+
61+
/* Contents zeroed on startup, see StartupSUBTRANS(). */
62+
"pg_subtrans",
63+
64+
/* end of list */
65+
NULL, /* pg_log will be set later */
66+
NULL
6767
};
6868

6969
static char *pgdata_exclude_files[] =

init.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ do_init(void)
6363
join_path_components(path, backup_path, BACKUP_CATALOG_CONF_FILE);
6464
fp = fopen(path, "wt");
6565
if (fp == NULL)
66-
elog(ERROR, "cannot create pg_probackup.conf: %s", strerror(errno));
66+
elog(ERROR, "cannot create %s: %s",
67+
BACKUP_CATALOG_CONF_FILE, strerror(errno));
6768

6869
fprintf(fp, "system-identifier = %li\n", _system_identifier);
6970
fprintf(fp, "\n");

0 commit comments

Comments
 (0)