Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9f038ee

Browse files
committed
Add support backup from replica.
1 parent43b7455 commit9f038ee

File tree

6 files changed

+129
-38
lines changed

6 files changed

+129
-38
lines changed

‎README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ server because of a reason or another. Its differential backup
1313
facility reduces the amount of data necessary to be taken between
1414
two consecutive backups.
1515

16+
Main features:
17+
* incremental backup from WAL and PTRACK
18+
* backup from replica
19+
* multithreaded backup and restore
20+
* autonomous backup without archive command (will need slot replication)
21+
1622
Download
1723
--------
1824

‎backup.c

Lines changed: 112 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const char *progname = "pg_arman";
4141
parray*backup_files_list;
4242
staticvolatileuint32total_copy_files_increment;
4343
staticuint32total_files_num;
44+
staticPGconn*start_stop_connect=NULL;
4445

4546
typedefstruct
4647
{
@@ -61,7 +62,7 @@ static void confirm_block_size(const char *name, int blcksz);
6162
staticvoidpg_start_backup(constchar*label,boolsmooth,pgBackup*backup);
6263
staticvoidpg_stop_backup(pgBackup*backup);
6364
staticboolpg_is_standby(void);
64-
staticvoidget_lsn(PGresult*res,XLogRecPtr*lsn);
65+
staticvoidget_lsn(PGconn*conn,PGresult*res,XLogRecPtr*lsn,boolstop_backup);
6566
staticvoidget_xid(PGresult*res,uint32*xid);
6667
staticvoidpg_ptrack_clear(void);
6768
staticchar*pg_ptrack_get_and_clear(Oidtablespace_oid,
@@ -74,7 +75,7 @@ static void create_file_list(parray *files,
7475
constchar*subdir,
7576
constchar*prefix,
7677
boolis_append);
77-
staticvoidwait_for_archive(pgBackup*backup,constchar*sql);
78+
staticvoidwait_for_archive(PGconn*conn,pgBackup*backup,constchar*sql,boolstop_backup);
7879
staticvoidmake_pagemap_from_ptrack(parray*files);
7980
staticvoidStreamLog(void*arg);
8081

@@ -112,7 +113,7 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
112113
pgBackup*prev_backup=NULL;
113114

114115
/* Block backup operations on a standby */
115-
if (pg_is_standby())
116+
if (pg_is_standby()&& !from_replica)
116117
elog(ERROR,"Backup cannot run on a standby.");
117118

118119
elog(LOG,"database backup start");
@@ -164,18 +165,21 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
164165
strncat(label," with pg_arman",lengthof(label));
165166
pg_start_backup(label,smooth_checkpoint,&current);
166167

167-
/* If backup_label does not exist in $PGDATA, stop taking backup */
168-
snprintf(path,lengthof(path),"%s/backup_label",pgdata);
169-
make_native_path(path);
170-
if (!fileExists(path))
171-
has_backup_label= false;
172-
173-
/* Leave if no backup file */
174-
if (!has_backup_label)
168+
if(!from_replica)
175169
{
176-
elog(LOG,"backup_label does not exist, stopping backup");
177-
pg_stop_backup(NULL);
178-
elog(ERROR,"backup_label does not exist in PGDATA.");
170+
/* If backup_label does not exist in $PGDATA, stop taking backup */
171+
snprintf(path,lengthof(path),"%s/backup_label",pgdata);
172+
make_native_path(path);
173+
if (!fileExists(path))
174+
has_backup_label= false;
175+
176+
/* Leave if no backup file */
177+
if (!has_backup_label)
178+
{
179+
elog(LOG,"backup_label does not exist, stopping backup");
180+
pg_stop_backup(NULL);
181+
elog(ERROR,"backup_label does not exist in PGDATA.");
182+
}
179183
}
180184

181185
/*
@@ -246,7 +250,7 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
246250
if (current.backup_mode==BACKUP_MODE_DIFF_PAGE)
247251
{
248252
/* Enforce archiving of last segment and wait for it to be here */
249-
wait_for_archive(&current,"SELECT * FROM pg_switch_xlog()");
253+
wait_for_archive(connection,&current,"SELECT * FROM pg_switch_xlog()", false);
250254

251255
/* Now build the page map */
252256
parray_qsort(backup_files_list,pgFileComparePathDesc);
@@ -563,6 +567,13 @@ check_server_version(void)
563567
(server_version /100) %100,
564568
server_version %100,"9.5");
565569

570+
if (from_replica&&server_version<90600)
571+
elog(ERROR,
572+
"server version is %d.%d.%d, must be %s or higher for backup from replica.",
573+
server_version /10000,
574+
(server_version /100) %100,
575+
server_version %100,"9.6");
576+
566577
/* confirm block_size (BLCKSZ) and wal_block_size (XLOG_BLCKSZ) */
567578
confirm_block_size("block_size",BLCKSZ);
568579
confirm_block_size("wal_block_size",XLOG_BLCKSZ);
@@ -601,16 +612,27 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
601612

602613
params[0]=label;
603614

604-
reconnect();
615+
if (start_stop_connect==NULL)
616+
start_stop_connect=pgut_connect(ERROR);
605617

606618
/* 2nd argument is 'fast'*/
607619
params[1]=smooth ?"false" :"true";
608-
res=execute("SELECT pg_start_backup($1, $2)",2,params);
620+
if (from_replica)
621+
res=pgut_execute(start_stop_connect,
622+
"SELECT pg_start_backup($1, $2, false)",
623+
2,
624+
params,
625+
ERROR);
626+
else
627+
res=pgut_execute(start_stop_connect,
628+
"SELECT pg_start_backup($1, $2)",
629+
2,
630+
params,
631+
ERROR);
609632

610633
if (backup!=NULL)
611-
get_lsn(res,&backup->start_lsn);
634+
get_lsn(start_stop_connect,res,&backup->start_lsn, false);
612635
PQclear(res);
613-
disconnect();
614636
}
615637

616638
staticvoid
@@ -670,7 +692,7 @@ pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_oid, size_t *res
670692
}
671693

672694
staticvoid
673-
wait_for_archive(pgBackup*backup,constchar*sql)
695+
wait_for_archive(PGconn*conn,pgBackup*backup,constchar*sql,boolstop_backup)
674696
{
675697
PGresult*res;
676698
charready_path[MAXPGPATH];
@@ -680,17 +702,18 @@ wait_for_archive(pgBackup *backup, const char *sql)
680702
TimeLineIDtli;
681703
XLogSegNotargetSegNo;
682704

683-
reconnect();
705+
if (conn==NULL)
706+
conn=pgut_connect(ERROR);
684707

685708
/* Remove annoying NOTICE messages generated by backend */
686-
res=execute("SET client_min_messages = warning;",0,NULL);
709+
res=pgut_execute(conn,"SET client_min_messages = warning;",0,NULL,ERROR);
687710
PQclear(res);
688711

689712
/* And execute the query wanted */
690-
res=execute(sql,0,NULL);
713+
res=pgut_execute(conn,sql,0,NULL,ERROR);
691714

692715
/* Get LSN from execution result */
693-
get_lsn(res,&lsn);
716+
get_lsn(conn,res,&lsn,stop_backup);
694717

695718
/*
696719
* Enforce TLI obtention if backup is not present as this code
@@ -720,13 +743,15 @@ wait_for_archive(pgBackup *backup, const char *sql)
720743

721744
PQclear(res);
722745

723-
res=execute(TXID_CURRENT_SQL,0,NULL);
746+
if (from_replica)
747+
res=pgut_execute(conn,TXID_CURRENT_IF_SQL,0,NULL,ERROR);
748+
else
749+
res=pgut_execute(conn,TXID_CURRENT_SQL,0,NULL,ERROR);
724750
if (backup!=NULL)
725751
{
726752
get_xid(res,&backup->recovery_xid);
727753
backup->recovery_time=time(NULL);
728754
}
729-
disconnect();
730755

731756
/* wait until switched WAL is archived */
732757
try_count=0;
@@ -756,17 +781,22 @@ pg_stop_backup(pgBackup *backup)
756781
PGresult*res;
757782
TimeLineIDtli;
758783

759-
reconnect();
784+
//reconnect();
785+
if (start_stop_connect==NULL)
786+
start_stop_connect=pgut_connect(ERROR);
760787

761788
/* Remove annoying NOTICE messages generated by backend */
762-
res=execute("SET client_min_messages = warning;",0,NULL);
789+
res=pgut_execute(start_stop_connect,"SET client_min_messages = warning;",0,NULL,ERROR);
763790
PQclear(res);
764791

765792
/* And execute the query wanted */
766-
res=execute("SELECT * FROM pg_stop_backup()",0,NULL);
793+
if (from_replica)
794+
res=pgut_execute(start_stop_connect,"SELECT * FROM pg_stop_backup(false)",0,NULL,ERROR);
795+
else
796+
res=pgut_execute(start_stop_connect,"SELECT * FROM pg_stop_backup()",0,NULL,ERROR);
767797

768798
/* Get LSN from execution result */
769-
get_lsn(res,&stop_backup_lsn);
799+
get_lsn(start_stop_connect,res,&stop_backup_lsn, true);
770800
PQclear(res);
771801

772802
/*
@@ -786,18 +816,33 @@ pg_stop_backup(pgBackup *backup)
786816
(uint32)backup->stop_lsn);
787817
}
788818

789-
res=execute(TXID_CURRENT_SQL,0,NULL);
819+
if (from_replica)
820+
res=pgut_execute(start_stop_connect,TXID_CURRENT_IF_SQL,0,NULL,ERROR);
821+
else
822+
res=pgut_execute(start_stop_connect,TXID_CURRENT_SQL,0,NULL,ERROR);
790823
if (backup!=NULL)
791824
{
792825
get_xid(res,&backup->recovery_xid);
793826
backup->recovery_time=time(NULL);
794827
}
795828
PQclear(res);
796-
disconnect();
829+
//disconnect();
830+
pgut_disconnect(start_stop_connect);
797831
}
798832
else
799-
wait_for_archive(backup,
800-
"SELECT * FROM pg_stop_backup()");
833+
{
834+
if (from_replica)
835+
wait_for_archive(start_stop_connect,
836+
backup,
837+
"SELECT * FROM pg_stop_backup(false)",
838+
true);
839+
else
840+
wait_for_archive(start_stop_connect,
841+
backup,
842+
"SELECT * FROM pg_stop_backup()",
843+
true);
844+
pgut_disconnect(start_stop_connect);
845+
}
801846
}
802847

803848

@@ -818,15 +863,15 @@ pg_is_standby(void)
818863
* Get LSN from result of pg_start_backup() or pg_stop_backup().
819864
*/
820865
staticvoid
821-
get_lsn(PGresult*res,XLogRecPtr*lsn)
866+
get_lsn(PGconn*conn,PGresult*res,XLogRecPtr*lsn,boolstop_backup)
822867
{
823868
uint32xlogid;
824869
uint32xrecoff;
825870

826-
if (res==NULL||PQntuples(res)!=1||PQnfields(res)!=1)
871+
if (res==NULL||PQntuples(res)!=1||(PQnfields(res)!=1&&PQnfields(res)!=3))
827872
elog(ERROR,
828873
"result of backup command is invalid: %s",
829-
PQerrorMessage(connection));
874+
PQerrorMessage(conn));
830875

831876
/*
832877
* Extract timeline and LSN from results of pg_stop_backup()
@@ -836,6 +881,36 @@ get_lsn(PGresult *res, XLogRecPtr *lsn)
836881
XLogDataFromLSN(PQgetvalue(res,0,0),&xlogid,&xrecoff);
837882
/* Calculate LSN */
838883
*lsn= (XLogRecPtr) ((uint64)xlogid <<32) |xrecoff;
884+
885+
if (stop_backup&&from_replica&&PQnfields(res)==3)
886+
{
887+
charpath[MAXPGPATH];
888+
charpath_backup_label[MAXPGPATH];
889+
charpath_tablespace_map[MAXPGPATH];
890+
FILE*fp;
891+
892+
pgBackupGetPath(&current,path,lengthof(path),DATABASE_DIR);
893+
snprintf(path_backup_label,lengthof(path_backup_label),"%s/backup_label",path);
894+
snprintf(path_tablespace_map,lengthof(path_tablespace_map),"%s/tablespace_map",path);
895+
896+
fp=fopen(path_backup_label,"w");
897+
if (fp==NULL)
898+
elog(ERROR,"can't open backup label file \"%s\": %s",
899+
path_backup_label,strerror(errno));
900+
901+
fwrite(PQgetvalue(res,0,1),1,strlen(PQgetvalue(res,0,1)),fp);
902+
fclose(fp);
903+
if (strlen(PQgetvalue(res,0,2))==0)
904+
return;
905+
906+
fp=fopen(path_tablespace_map,"w");
907+
if (fp==NULL)
908+
elog(ERROR,"can't open tablespace map file \"%s\": %s",
909+
path_tablespace_map,strerror(errno));
910+
911+
fwrite(PQgetvalue(res,0,2),1,strlen(PQgetvalue(res,0,2)),fp);
912+
fclose(fp);
913+
}
839914
}
840915

841916
/*

‎doc/pg_arman.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,18 @@ absolute paths; relative paths are not allowed.
241241
Only files exceeded one of those settings are deleted.
242242

243243
**-j**=NUMBER /**--threads**=NUMBER:
244-
Number of threads for backup.
244+
Number of threads for backup.
245245

246246
**--stream**:
247247
Enable stream replication for save WAL during backup process.
248248

249249
**--disable-ptrack-clear**:
250250
Disable clear ptrack files for postgres without ptrack patch.
251251

252+
**--from-replica**:
253+
Use non exclusive start backup for replica. Only for 9.6 and higher.
254+
255+
252256
###RESTORE OPTIONS
253257

254258
The parameters whose name start are started with --recovery refer to

‎expected/option.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Backup options:
2828
--keep-data-days=DAY keep enough data backup to recover to DAY days age
2929
--disable-ptrack-clear disable clear ptrack for postgres without ptrack
3030
--backup-pg-log start backup pg_log directory
31+
--from-replica use non exclusive start backup for replica
3132

3233
Restore options:
3334
--recovery-target-time time stamp up to which recovery will proceed

‎pg_arman.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static intkeep_data_generations = KEEP_INFINITE;
3636
staticintkeep_data_days=KEEP_INFINITE;
3737
intnum_threads=1;
3838
boolstream_wal= false;
39+
boolfrom_replica= false;
3940
booldisable_ptrack_clear= false;
4041
staticboolbackup_logs= false;
4142
staticboolbackup_validate= false;
@@ -69,6 +70,7 @@ static pgut_option options[] =
6970
{'b',10,"backup-pg-log",&backup_logs },
7071
{'f','b',"backup-mode",opt_backup_mode,SOURCE_ENV },
7172
{'b','C',"smooth-checkpoint",&smooth_checkpoint,SOURCE_ENV },
73+
{'b',12,"from-replica",&from_replica },
7274
/* options with only long name (keep-xxx) */
7375
{'i',1,"keep-data-generations",&keep_data_generations,SOURCE_ENV },
7476
{'i',2,"keep-data-days",&keep_data_days,SOURCE_ENV },
@@ -250,6 +252,7 @@ pgut_help(bool details)
250252
printf(_(" --keep-data-days=DAY keep enough data backup to recover to DAY days age\n"));
251253
printf(_(" --disable-ptrack-clear disable clear ptrack for postgres without ptrack\n"));
252254
printf(_(" --backup-pg-log start backup pg_log directory\n"));
255+
printf(_(" --from-replica use non exclusive start backup for replica\n"));
253256
printf(_("\nRestore options:\n"));
254257
printf(_(" --recovery-target-time time stamp up to which recovery will proceed\n"));
255258
printf(_(" --recovery-target-xid transaction ID up to which recovery will proceed\n"));

‎pg_arman.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
/* Query to fetch current transaction ID */
2929
#defineTXID_CURRENT_SQL"SELECT txid_current();"
30+
#defineTXID_CURRENT_IF_SQL"SELECT txid_snapshot_xmax(txid_current_snapshot());"
3031

3132
/* Directory/File names */
3233
#defineDATABASE_DIR"database"
@@ -211,6 +212,7 @@ extern parray *backup_files_list;
211212

212213
externintnum_threads;
213214
externboolstream_wal;
215+
externboolfrom_replica;
214216
externbooldisable_ptrack_clear;
215217
externboolprogress;
216218

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp