Skip to content

Commit ee7b993

Browse files
committed
Merge tag '2.0.15' into stable
2 parents 0912cba + f9e36ee commit ee7b993

34 files changed

+2675
-1015
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ Regardless of the chosen backup type, all backups taken with `pg_probackup` supp
4242
* Configuration files outside of PostgreSQL data directory are not included into the backup and should be backed up separately.
4343

4444
## Installation and Setup
45+
### Linux Installation
46+
```shell
47+
#DEB Ubuntu|Debian Packages
48+
echo "deb [arch=amd64] http://repo.postgrespro.ru/pg_probackup/deb/ $(lsb_release -cs) main-$(lsb_release -cs)" > /etc/apt/sources.list.d/pg_probackup.list
49+
wget -O - http://repo.postgrespro.ru/pg_probackup/keys/GPG-KEY-PG_PROBACKUP | apt-key add - && apt-get update
50+
apt-get install pg-probackup-(10|9.6|9.5)
51+
52+
#DEB-SRC Packages
53+
echo "deb-src [arch=amd64] http://repo.postgrespro.ru/pg_probackup/deb/ $(lsb_release -cs) main-$(lsb_release -cs)" >>\
54+
/etc/apt/sources.list.d/pg_probackup.list
55+
```
56+
57+
```shell
58+
#RPM Centos Packages
59+
rpm -ivh http://repo.postgrespro.ru/pg_probackup/keys/pg_probackup-repo-centos.noarch.rpm
60+
yum install pg_probackup-(10|9.6|9.5)
61+
```
4562

4663
To compile `pg_probackup`, you must have a PostgreSQL installation and raw source tree. To install `pg_probackup`, execute this in the module's directory:
4764

src/archive.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ do_archive_push(char *wal_file_path, char *wal_file_name, bool overwrite)
6363

6464
elog(INFO, "pg_probackup archive-push from %s to %s", absolute_wal_file_path, backup_wal_file_path);
6565

66-
#ifdef HAVE_LIBZ
6766
if (compress_alg == PGLZ_COMPRESS)
6867
elog(ERROR, "pglz compression is not supported");
68+
69+
#ifdef HAVE_LIBZ
6970
if (compress_alg == ZLIB_COMPRESS)
7071
is_compress = IsXLogFileName(wal_file_name);
7172
#endif

src/backup.c

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ static pthread_mutex_t start_stream_mut = PTHREAD_MUTEX_INITIALIZER;
5252
static pthread_t stream_thread;
5353

5454
static int is_ptrack_enable = false;
55+
bool is_ptrack_support = false;
5556
bool is_checksum_enabled = false;
57+
bool exclusive_backup = false;
5658

5759
/* Backup connections */
5860
static PGconn *backup_conn = NULL;
@@ -63,7 +65,6 @@ static PGconn *backup_conn_replication = NULL;
6365
static int server_version = 0;
6466
static char server_version_str[100] = "";
6567

66-
static bool exclusive_backup = false;
6768
/* Is pg_start_backup() was executed */
6869
static bool backup_in_progress = false;
6970
/* Is pg_stop_backup() was sent */
@@ -505,7 +506,7 @@ do_backup_instance(void)
505506

506507
/*
507508
* It`s illegal to take PTRACK backup if LSN from ptrack_control() is not equal to
508-
* start_backup LSN of previous backup
509+
* stort_backup LSN of previous backup
509510
*/
510511
if (current.backup_mode == BACKUP_MODE_DIFF_PTRACK)
511512
{
@@ -622,7 +623,7 @@ do_backup_instance(void)
622623
else
623624
dir_name = file->path;
624625

625-
elog(LOG, "Create directory \"%s\"", dir_name);
626+
elog(VERBOSE, "Create directory \"%s\"", dir_name);
626627
pgBackupGetPath(&current, database_path, lengthof(database_path),
627628
DATABASE_DIR);
628629

@@ -653,9 +654,10 @@ do_backup_instance(void)
653654
}
654655

655656
/* Run threads */
657+
elog(LOG, "Start transfering data files");
656658
for (i = 0; i < num_threads; i++)
657659
{
658-
elog(LOG, "Start thread num:%i", i);
660+
elog(VERBOSE, "Start thread num: %i", i);
659661

660662
if (!is_remote_backup)
661663
pthread_create(&backup_threads[i], NULL,
@@ -671,10 +673,9 @@ do_backup_instance(void)
671673
for (i = 0; i < num_threads; i++)
672674
{
673675
pthread_join(backup_threads[i], NULL);
674-
if (backup_threads_args[i]->thread_backup_conn != NULL)
675-
pgut_disconnect(backup_threads_args[i]->thread_backup_conn);
676676
pg_free(backup_threads_args[i]);
677677
}
678+
elog(LOG, "Data files are transfered");
678679

679680
/* clean previous backup file list */
680681
if (prev_backup_filelist)
@@ -743,7 +744,6 @@ do_backup_instance(void)
743744
int
744745
do_backup(time_t start_time)
745746
{
746-
bool is_ptrack_support;
747747

748748
/* PGDATA and BACKUP_MODE are always required */
749749
if (pgdata == NULL)
@@ -771,6 +771,14 @@ do_backup(time_t start_time)
771771
current.checksum_version = get_data_checksum_version(true);
772772

773773
is_checksum_enabled = pg_checksum_enable();
774+
775+
if (is_checksum_enabled)
776+
elog(LOG, "This PostgreSQL instance initialized with data block checksums. "
777+
"Data block corruption will be detected");
778+
else
779+
elog(WARNING, "This PostgreSQL instance initialized without data block checksums. "
780+
"pg_probackup have no way to detect data block corruption without them. "
781+
"Reinitialize PGDATA with option '--data-checksums'.");
774782

775783
StrNCpy(current.server_version, server_version_str,
776784
sizeof(current.server_version));
@@ -857,7 +865,7 @@ do_backup(time_t start_time)
857865
* After successfil backup completion remove backups
858866
* which are expired according to retention policies
859867
*/
860-
if (delete_expired)
868+
if (delete_expired || delete_wal)
861869
do_retention_purge();
862870

863871
return 0;
@@ -1592,25 +1600,19 @@ pg_stop_backup(pgBackup *backup)
15921600
*/
15931601
sent = pgut_send(conn,
15941602
"SELECT"
1595-
" labelfile,"
15961603
" txid_snapshot_xmax(txid_current_snapshot()),"
15971604
" current_timestamp(0)::timestamptz,"
15981605
" lsn,"
1606+
" labelfile,"
15991607
" spcmapfile"
16001608
" FROM pg_stop_backup(false)",
16011609
0, NULL, WARNING);
16021610
}
16031611
else
16041612
{
16051613

1606-
tablespace_map_content = pgut_execute(conn,
1607-
"SELECT pg_read_file('tablespace_map', 0, size, true)"
1608-
" FROM pg_stat_file('tablespace_map', true)",
1609-
0, NULL, true);
1610-
16111614
sent = pgut_send(conn,
16121615
"SELECT"
1613-
" pg_read_file('backup_label') as labelfile,"
16141616
" txid_snapshot_xmax(txid_current_snapshot()),"
16151617
" current_timestamp(0)::timestamptz,"
16161618
" pg_stop_backup() as lsn",
@@ -1668,7 +1670,7 @@ pg_stop_backup(pgBackup *backup)
16681670
backup_in_progress = false;
16691671

16701672
/* Extract timeline and LSN from results of pg_stop_backup() */
1671-
XLogDataFromLSN(PQgetvalue(res, 0, 3), &xlogid, &xrecoff);
1673+
XLogDataFromLSN(PQgetvalue(res, 0, 2), &xlogid, &xrecoff);
16721674
/* Calculate LSN */
16731675
stop_backup_lsn = (XLogRecPtr) ((uint64) xlogid << 32) | xrecoff;
16741676

@@ -1682,61 +1684,57 @@ pg_stop_backup(pgBackup *backup)
16821684
(uint32) (stop_backup_lsn >> 32), (uint32) (stop_backup_lsn));
16831685

16841686
/* Write backup_label and tablespace_map */
1685-
Assert(PQnfields(res) >= 4);
1686-
pgBackupGetPath(&current, path, lengthof(path), DATABASE_DIR);
1687-
1688-
/* Write backup_label */
1689-
join_path_components(backup_label, path, PG_BACKUP_LABEL_FILE);
1690-
fp = fopen(backup_label, "w");
1691-
if (fp == NULL)
1692-
elog(ERROR, "can't open backup label file \"%s\": %s",
1693-
backup_label, strerror(errno));
1694-
1695-
len = strlen(PQgetvalue(res, 0, 0));
1696-
if (fwrite(PQgetvalue(res, 0, 0), 1, len, fp) != len ||
1697-
fflush(fp) != 0 ||
1698-
fsync(fileno(fp)) != 0 ||
1699-
fclose(fp))
1700-
elog(ERROR, "can't write backup label file \"%s\": %s",
1701-
backup_label, strerror(errno));
1702-
1703-
/*
1704-
* It's vital to check if backup_files_list is initialized,
1705-
* because we could get here because the backup was interrupted
1706-
*/
1707-
if (backup_files_list)
1687+
if (!exclusive_backup)
17081688
{
1709-
file = pgFileNew(backup_label, true);
1710-
calc_file_checksum(file);
1711-
free(file->path);
1712-
file->path = strdup(PG_BACKUP_LABEL_FILE);
1713-
parray_append(backup_files_list, file);
1689+
Assert(PQnfields(res) >= 4);
1690+
pgBackupGetPath(&current, path, lengthof(path), DATABASE_DIR);
1691+
1692+
/* Write backup_label */
1693+
join_path_components(backup_label, path, PG_BACKUP_LABEL_FILE);
1694+
fp = fopen(backup_label, "w");
1695+
if (fp == NULL)
1696+
elog(ERROR, "can't open backup label file \"%s\": %s",
1697+
backup_label, strerror(errno));
1698+
1699+
len = strlen(PQgetvalue(res, 0, 3));
1700+
if (fwrite(PQgetvalue(res, 0, 3), 1, len, fp) != len ||
1701+
fflush(fp) != 0 ||
1702+
fsync(fileno(fp)) != 0 ||
1703+
fclose(fp))
1704+
elog(ERROR, "can't write backup label file \"%s\": %s",
1705+
backup_label, strerror(errno));
1706+
1707+
/*
1708+
* It's vital to check if backup_files_list is initialized,
1709+
* because we could get here because the backup was interrupted
1710+
*/
1711+
if (backup_files_list)
1712+
{
1713+
file = pgFileNew(backup_label, true);
1714+
calc_file_checksum(file);
1715+
free(file->path);
1716+
file->path = strdup(PG_BACKUP_LABEL_FILE);
1717+
parray_append(backup_files_list, file);
1718+
}
17141719
}
17151720

1716-
if (sscanf(PQgetvalue(res, 0, 1), XID_FMT, &recovery_xid) != 1)
1721+
if (sscanf(PQgetvalue(res, 0, 0), XID_FMT, &recovery_xid) != 1)
17171722
elog(ERROR,
17181723
"result of txid_snapshot_xmax() is invalid: %s",
17191724
PQerrorMessage(conn));
1720-
if (!parse_time(PQgetvalue(res, 0, 2), &recovery_time))
1725+
if (!parse_time(PQgetvalue(res, 0, 1), &recovery_time))
17211726
elog(ERROR,
17221727
"result of current_timestamp is invalid: %s",
17231728
PQerrorMessage(conn));
17241729

1725-
/* Get content for tablespace_map from pg_read_file('tablespace_map') in case of exclusive
1726-
* or from stop_backup results in case of non-exclusive backup
1730+
/* Get content for tablespace_map from stop_backup results
1731+
* in case of non-exclusive backup
17271732
*/
1728-
if (exclusive_backup)
1729-
{
1730-
Assert(tablespace_map_content);
1731-
1732-
if (PQresultStatus(tablespace_map_content) == PGRES_TUPLES_OK)
1733-
val = PQgetvalue(tablespace_map_content, 0, 0);
1734-
}
1735-
else
1733+
if (!exclusive_backup)
17361734
val = PQgetvalue(res, 0, 4);
17371735

17381736
/* Write tablespace_map */
1739-
if (val && strlen(val) > 0)
1737+
if (!exclusive_backup && val && strlen(val) > 0)
17401738
{
17411739
char tablespace_map[MAXPGPATH];
17421740

@@ -1958,7 +1956,7 @@ backup_files(void *arg)
19581956
current.backup_mode))
19591957
{
19601958
file->write_size = BYTES_INVALID;
1961-
elog(LOG, "File \"%s\" was not copied to backup", file->path);
1959+
elog(VERBOSE, "File \"%s\" was not copied to backup", file->path);
19621960
continue;
19631961
}
19641962
}
@@ -1967,7 +1965,7 @@ backup_files(void *arg)
19671965
file))
19681966
{
19691967
file->write_size = BYTES_INVALID;
1970-
elog(LOG, "File \"%s\" was not copied to backup", file->path);
1968+
elog(VERBOSE, "File \"%s\" was not copied to backup", file->path);
19711969
continue;
19721970
}
19731971

@@ -1977,6 +1975,11 @@ backup_files(void *arg)
19771975
else
19781976
elog(LOG, "unexpected file type %d", buf.st_mode);
19791977
}
1978+
1979+
/* Close connection */
1980+
if (arguments->thread_backup_conn)
1981+
pgut_disconnect(arguments->thread_backup_conn);
1982+
19801983
}
19811984

19821985
/*
@@ -2264,6 +2267,8 @@ set_cfs_datafiles(parray *files, const char *root, char *relative, size_t i)
22642267
char *relative_prev_file;
22652268

22662269
cfs_tblspc_path = strdup(relative);
2270+
if(!cfs_tblspc_path)
2271+
elog(ERROR, "Out of memory");
22672272
len = strlen("/pg_compression");
22682273
cfs_tblspc_path[strlen(cfs_tblspc_path) - len] = 0;
22692274
elog(VERBOSE, "CFS DIRECTORY %s, pg_compression path: %s", cfs_tblspc_path, relative);
@@ -2398,6 +2403,7 @@ make_pagemap_from_ptrack(parray *files)
23982403
char *ptrack_nonparsed = NULL;
23992404
size_t ptrack_nonparsed_size = 0;
24002405

2406+
elog(LOG, "Compiling pagemap");
24012407
for (i = 0; i < parray_num(files); i++)
24022408
{
24032409
pgFile *file = (pgFile *) parray_get(files, i);
@@ -2492,6 +2498,9 @@ make_pagemap_from_ptrack(parray *files)
24922498
}
24932499
}
24942500
}
2501+
elog(LOG, "Pagemap compiled");
2502+
// res = pgut_execute(backup_conn, "SET client_min_messages = warning;", 0, NULL, true);
2503+
// PQclear(pgut_execute(backup_conn, "CHECKPOINT;", 0, NULL, true));
24952504
}
24962505

24972506

@@ -2711,7 +2720,9 @@ pg_ptrack_get_block(backup_files_args *arguments,
27112720
{
27122721
arguments->thread_backup_conn = pgut_connect(pgut_dbname);
27132722
}
2714-
arguments->thread_cancel_conn = PQgetCancel(arguments->thread_backup_conn);
2723+
2724+
if (arguments->thread_cancel_conn == NULL)
2725+
arguments->thread_cancel_conn = PQgetCancel(arguments->thread_backup_conn);
27152726

27162727
//elog(LOG, "db %i pg_ptrack_get_block(%i, %i, %u)",dbOid, tblsOid, relOid, blknum);
27172728
res = pgut_execute_parallel(arguments->thread_backup_conn,

src/data.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ read_page_from_file(pgFile *file, BlockNumber blknum,
190190
}
191191

192192
/* Verify checksum */
193-
if(current.checksum_version && is_checksum_enabled)
193+
if(current.checksum_version)
194194
{
195195
/*
196196
* If checksum is wrong, sleep a bit and then try again
@@ -266,10 +266,29 @@ backup_data_page(backup_files_args *arguments,
266266

267267
if (result == 1)
268268
page_is_valid = true;
269+
270+
/*
271+
* If ptrack support is available use it to get invalid block
272+
* instead of rereading it 99 times
273+
*/
274+
//elog(WARNING, "Checksum_Version: %i", current.checksum_version ? 1 : 0);
275+
276+
if (result == -1 && is_ptrack_support)
277+
{
278+
elog(WARNING, "File %s, block %u, try to fetch via SQL",
279+
file->path, blknum);
280+
break;
281+
}
269282
}
283+
/*
284+
* If page is not valid after 100 attempts to read it
285+
* throw an error.
286+
*/
287+
if(!page_is_valid && !is_ptrack_support)
288+
elog(ERROR, "Data file checksum mismatch. Canceling backup");
270289
}
271290

272-
if (backup_mode == BACKUP_MODE_DIFF_PTRACK)
291+
if (backup_mode == BACKUP_MODE_DIFF_PTRACK || (!page_is_valid && is_ptrack_support))
273292
{
274293
size_t page_size = 0;
275294

@@ -285,8 +304,7 @@ backup_data_page(backup_files_args *arguments,
285304
}
286305
else if (page_size != BLCKSZ)
287306
{
288-
elog(ERROR, "File: %s, block %u, expected block size %lu,"
289-
"but read %d, try again",
307+
elog(ERROR, "File: %s, block %u, expected block size %lu, but read %d",
290308
file->path, absolute_blknum, page_size, BLCKSZ);
291309
}
292310
else

0 commit comments

Comments
 (0)