@@ -475,6 +475,8 @@ do_backup_instance(void)
475
475
pgBackup * prev_backup = NULL ;
476
476
parray * prev_backup_filelist = NULL ;
477
477
478
+ pgFile * pg_control = NULL ;
479
+
478
480
elog (LOG , "Database backup start" );
479
481
480
482
/* Initialize size summary */
@@ -754,9 +756,34 @@ do_backup_instance(void)
754
756
parray_free (prev_backup_filelist );
755
757
}
756
758
759
+ /* In case of backup from replica >= 9.6 we must fix minRecPoint,
760
+ * First we must find pg_control in backup_files_list.
761
+ */
762
+ if (current .from_replica && !exclusive_backup )
763
+ {
764
+ char pg_control_path [MAXPGPATH ];
765
+
766
+ snprintf (pg_control_path , sizeof (pg_control_path ), "%s/%s" , pgdata , "global/pg_control" );
767
+
768
+ for (i = 0 ; i < parray_num (backup_files_list ); i ++ )
769
+ {
770
+ pgFile * tmp_file = (pgFile * ) parray_get (backup_files_list , i );
771
+
772
+ if (strcmp (tmp_file -> path , pg_control_path ) == 0 )
773
+ {
774
+ pg_control = tmp_file ;
775
+ break ;
776
+ }
777
+ }
778
+ }
779
+
780
+
757
781
/* Notify end of backup */
758
782
pg_stop_backup (& current );
759
783
784
+ if (current .from_replica && !exclusive_backup )
785
+ set_min_recovery_point (pg_control , database_path , current .stop_lsn );
786
+
760
787
/* Add archived xlog files into the list of files of this backup */
761
788
if (stream_wal )
762
789
{
@@ -883,7 +910,7 @@ do_backup(time_t start_time)
883
910
}
884
911
}
885
912
886
- if (current .from_replica )
913
+ if (current .from_replica && exclusive_backup )
887
914
{
888
915
/* Check master connection options */
889
916
if (master_host == NULL )
@@ -1089,8 +1116,11 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
1089
1116
1090
1117
params [0 ] = label ;
1091
1118
1092
- /* For replica we call pg_start_backup() on master */
1093
- conn = (backup -> from_replica ) ? master_conn : backup_conn ;
1119
+ /* For 9.5 replica we call pg_start_backup() on master */
1120
+ if (backup -> from_replica && exclusive_backup )
1121
+ conn = master_conn ;
1122
+ else
1123
+ conn = backup_conn ;
1094
1124
1095
1125
/* 2nd argument is 'fast'*/
1096
1126
params [1 ] = smooth ? "false" : "true" ;
@@ -1118,16 +1148,18 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
1118
1148
1119
1149
PQclear (res );
1120
1150
1121
- if (current .backup_mode == BACKUP_MODE_DIFF_PAGE )
1151
+ if (current .backup_mode == BACKUP_MODE_DIFF_PAGE &&
1152
+ (!(backup -> from_replica && !exclusive_backup )))
1122
1153
/*
1123
1154
* Switch to a new WAL segment. It is necessary to get archived WAL
1124
1155
* segment, which includes start LSN of current backup.
1156
+ * Don`t do this for replica backups unless it`s PG 9.5
1125
1157
*/
1126
1158
pg_switch_wal (conn );
1127
1159
1128
1160
if (current .backup_mode == BACKUP_MODE_DIFF_PAGE )
1129
1161
/* In PAGE mode wait for current segment... */
1130
- wait_wal_lsn (backup -> start_lsn , true, false);
1162
+ wait_wal_lsn (backup -> start_lsn , true, false);
1131
1163
/*
1132
1164
* Do not wait start_lsn for stream backup.
1133
1165
* Because WAL streaming will start after pg_start_backup() in stream
@@ -1137,8 +1169,10 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
1137
1169
/* ...for others wait for previous segment */
1138
1170
wait_wal_lsn (backup -> start_lsn , true, true);
1139
1171
1140
- /* Wait for start_lsn to be replayed by replica */
1141
- if (backup -> from_replica )
1172
+ /* In case of backup from replica for PostgreSQL 9.5
1173
+ * wait for start_lsn to be replayed by replica
1174
+ */
1175
+ if (backup -> from_replica && exclusive_backup )
1142
1176
wait_replica_wal_lsn (backup -> start_lsn , true);
1143
1177
}
1144
1178
@@ -1488,7 +1522,7 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
1488
1522
GetXLogFileName (wal_segment , tli , targetSegNo , xlog_seg_size );
1489
1523
1490
1524
/*
1491
- * In pg_start_backup we wait for 'lsn' in 'pg_wal' directory iff it is
1525
+ * In pg_start_backup we wait for 'lsn' in 'pg_wal' directory if it is
1492
1526
* stream and non-page backup. Page backup needs archived WAL files, so we
1493
1527
* wait for 'lsn' in archive 'wal' directory for page backups.
1494
1528
*
@@ -1509,7 +1543,12 @@ wait_wal_lsn(XLogRecPtr lsn, bool is_start_lsn, bool wait_prev_segment)
1509
1543
{
1510
1544
join_path_components (wal_segment_path , arclog_path , wal_segment );
1511
1545
wal_segment_dir = arclog_path ;
1512
- timeout = archive_timeout ;
1546
+
1547
+ if (archive_timeout > 0 )
1548
+ timeout = archive_timeout ;
1549
+ else
1550
+ timeout = ARCHIVE_TIMEOUT_DEFAULT ;
1551
+
1513
1552
}
1514
1553
1515
1554
if (wait_prev_segment )
@@ -1669,7 +1708,7 @@ pg_stop_backup(pgBackup *backup)
1669
1708
PGresult * tablespace_map_content = NULL ;
1670
1709
uint32 lsn_hi ;
1671
1710
uint32 lsn_lo ;
1672
- XLogRecPtr restore_lsn = InvalidXLogRecPtr ;
1711
+ // XLogRecPtr restore_lsn = InvalidXLogRecPtr;
1673
1712
int pg_stop_backup_timeout = 0 ;
1674
1713
char path [MAXPGPATH ];
1675
1714
char backup_label [MAXPGPATH ];
@@ -1689,16 +1728,21 @@ pg_stop_backup(pgBackup *backup)
1689
1728
if (!backup_in_progress )
1690
1729
elog (ERROR , "backup is not in progress" );
1691
1730
1692
- /* For replica we call pg_stop_backup() on master */
1693
- conn = (current .from_replica ) ? master_conn : backup_conn ;
1731
+ /* For 9.5 replica we call pg_stop_backup() on master */
1732
+ if (current .from_replica && exclusive_backup )
1733
+ conn = master_conn ;
1734
+ else
1735
+ conn = backup_conn ;
1694
1736
1695
1737
/* Remove annoying NOTICE messages generated by backend */
1696
1738
res = pgut_execute (conn , "SET client_min_messages = warning;" ,
1697
1739
0 , NULL );
1698
1740
PQclear (res );
1699
1741
1700
- /* Create restore point */
1701
- if (backup != NULL )
1742
+ /* Create restore point
1743
+ * only if it`s backup from master, or exclusive replica(wich connects to master)
1744
+ */
1745
+ if (backup != NULL && (!current .from_replica || (current .from_replica && exclusive_backup )))
1702
1746
{
1703
1747
const char * params [1 ];
1704
1748
char name [1024 ];
@@ -1716,7 +1760,7 @@ pg_stop_backup(pgBackup *backup)
1716
1760
/* Extract timeline and LSN from the result */
1717
1761
XLogDataFromLSN (PQgetvalue (res , 0 , 0 ), & lsn_hi , & lsn_lo );
1718
1762
/* Calculate LSN */
1719
- restore_lsn = ((uint64 ) lsn_hi ) << 32 | lsn_lo ;
1763
+ // restore_lsn = ((uint64) lsn_hi) << 32 | lsn_lo;
1720
1764
PQclear (res );
1721
1765
}
1722
1766
@@ -1737,14 +1781,29 @@ pg_stop_backup(pgBackup *backup)
1737
1781
* Stop the non-exclusive backup. Besides stop_lsn it returns from
1738
1782
* pg_stop_backup(false) copy of the backup label and tablespace map
1739
1783
* so they can be written to disk by the caller.
1784
+ * In case of backup from replica >= 9.6 we do not trust minRecPoint
1785
+ * and stop_backup LSN, so we use latest replayed LSN as STOP LSN.
1740
1786
*/
1741
- stop_backup_query = "SELECT"
1742
- " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1743
- " current_timestamp(0)::timestamptz,"
1744
- " lsn,"
1745
- " labelfile,"
1746
- " spcmapfile"
1747
- " FROM pg_catalog.pg_stop_backup(false)" ;
1787
+ if (current .from_replica )
1788
+ stop_backup_query = "SELECT"
1789
+ " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1790
+ " current_timestamp(0)::timestamptz,"
1791
+ #if PG_VERSION_NUM >= 100000
1792
+ " pg_catalog.pg_last_wal_replay_lsn(),"
1793
+ #else
1794
+ " pg_catalog.pg_last_xlog_replay_location(),"
1795
+ #endif
1796
+ " labelfile,"
1797
+ " spcmapfile"
1798
+ " FROM pg_catalog.pg_stop_backup(false)" ;
1799
+ else
1800
+ stop_backup_query = "SELECT"
1801
+ " pg_catalog.txid_snapshot_xmax(pg_catalog.txid_current_snapshot()),"
1802
+ " current_timestamp(0)::timestamptz,"
1803
+ " lsn,"
1804
+ " labelfile,"
1805
+ " spcmapfile"
1806
+ " FROM pg_catalog.pg_stop_backup(false)" ;
1748
1807
1749
1808
}
1750
1809
else
@@ -1832,13 +1891,13 @@ pg_stop_backup(pgBackup *backup)
1832
1891
1833
1892
if (!XRecOffIsValid (stop_backup_lsn ))
1834
1893
{
1835
- stop_backup_lsn = restore_lsn ;
1894
+ if (XRecOffIsNull (stop_backup_lsn ))
1895
+ stop_backup_lsn = stop_backup_lsn + SizeOfXLogLongPHD ;
1896
+ else
1897
+ elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1898
+ (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
1836
1899
}
1837
1900
1838
- if (!XRecOffIsValid (stop_backup_lsn ))
1839
- elog (ERROR , "Invalid stop_backup_lsn value %X/%X" ,
1840
- (uint32 ) (stop_backup_lsn >> 32 ), (uint32 ) (stop_backup_lsn ));
1841
-
1842
1901
/* Write backup_label and tablespace_map */
1843
1902
if (!exclusive_backup )
1844
1903
{
@@ -1939,7 +1998,7 @@ pg_stop_backup(pgBackup *backup)
1939
1998
stream_xlog_path [MAXPGPATH ];
1940
1999
1941
2000
/* Wait for stop_lsn to be received by replica */
1942
- if (backup -> from_replica )
2001
+ if (current . from_replica )
1943
2002
wait_replica_wal_lsn (stop_backup_lsn , false);
1944
2003
/*
1945
2004
* Wait for stop_lsn to be archived or streamed.
@@ -1962,10 +2021,12 @@ pg_stop_backup(pgBackup *backup)
1962
2021
1963
2022
elog (LOG , "Getting the Recovery Time from WAL" );
1964
2023
2024
+ /* iterate over WAL from stop_backup lsn to start_backup lsn */
1965
2025
if (!read_recovery_info (xlog_path , backup -> tli , xlog_seg_size ,
1966
2026
backup -> start_lsn , backup -> stop_lsn ,
1967
2027
& backup -> recovery_time , & backup -> recovery_xid ))
1968
2028
{
2029
+ elog (LOG , "Failed to find Recovery Time in WAL. Forced to trust current_timestamp" );
1969
2030
backup -> recovery_time = recovery_time ;
1970
2031
backup -> recovery_xid = recovery_xid ;
1971
2032
}
@@ -2074,7 +2135,7 @@ backup_files(void *arg)
2074
2135
elog (ERROR , "interrupted during backup" );
2075
2136
2076
2137
if (progress )
2077
- elog (LOG , "Progress: (%d/%d). Process file \"%s\"" ,
2138
+ elog (INFO , "Progress: (%d/%d). Process file \"%s\"" ,
2078
2139
i + 1 , n_backup_files_list , file -> path );
2079
2140
2080
2141
/* stat file to check its current state */
@@ -2168,7 +2229,7 @@ backup_files(void *arg)
2168
2229
file -> path , file -> write_size );
2169
2230
}
2170
2231
else
2171
- elog (LOG , "unexpected file type %d" , buf .st_mode );
2232
+ elog (WARNING , "unexpected file type %d" , buf .st_mode );
2172
2233
}
2173
2234
2174
2235
/* Close connection */
0 commit comments