从代码层判断 pg_basebackup 是否已正常结束 - 暨改进建议
背景
用户通常会使用pg_basebackup来对PostgreSQL实施在线备份,对于超级大的数据库实例,可能需要备份很久。
如果将任务分解来看,假设备份是任务流中的一个步骤,如果设置了超时时间,那么在超时导致该步骤失败之后,如何判断pg_basebackup是否已执行成功?
1、从pg_basebackup的源码中分析,文件是否有备份顺序,是否可能从某些文件是否存在来判断?
2、从pg_basebackup的返回值或STDOUT中判断。
从pg_basebackup的源码中分析
pg_basebackup的源码
src/bin/pg_basebackup/pg_basebackup.c
int
main(int argc, char **argv)
{
..............
BaseBackup();
success = true;
return 0;
}
static void
BaseBackup(void)
{
PGresult *res;
char *sysidentifier;
TimeLineID latesttli;
TimeLineID starttli;
char *basebkp;
char escaped_label[MAXPGPATH];
char *maxrate_clause = NULL;
int i;
char xlogstart[64];
char xlogend[64];
int minServerMajor,
maxServerMajor;
int serverVersion,
serverMajor;
....................
/* Free the recovery.conf contents */
destroyPQExpBuffer(recoveryconfcontents);
/*
* End of copy data. Final result is already checked inside the loop.
*/
PQclear(res);
PQfinish(conn);
/*
* Make data persistent on disk once backup is completed. For tar format
* once syncing the parent directory is fine, each tar file created per
* tablespace has been already synced. In plain format, all the data of
* the base directory is synced, taking into account all the tablespaces.
* Errors are not considered fatal.
*/
if (do_sync)
{
if (format == 't')
{
if (strcmp(basedir, "-") != 0)
(void) fsync_fname(basedir, true, progname);
}
else
{
(void) fsync_pgdata(basedir, progname, serverVersion);
}
}
// 改进可以写到这个位置,用户识别后,可以删除这个文件。
if (verbose)
fprintf(stderr, _("%s: base backup completed\n"), progname);
}
在结束时,并没有特别的输出,同时对源端文件的扫描也没有特定的顺序,或者结束时,并没有写特殊的标记文件。
如果需要通过备份内容来识别pg_basebackup是否结束,需要改进pg_basebackup,建议:
1、备份开始时,在本地(目标端),写一个标签文件,记录本次备份的开始时间
2、结束时,修改这个标签文件,记录结束时间。
那么可以查看这个文件来判断pg_basebackup是否结束。
从pg_basebackup的返回值或STDOUT中判断
实际上,从pg_basebackup源码可以看到,如果备份开启了 -v 参数,那么在备份结束后,会输出日志
fprintf(stderr, _("%s: base backup completed\n"), progname);
参数
-v
--verbose
Enables verbose mode. Will output some extra steps during startup and shutdown, as well as show the exact file name that is currently being processed if progress reporting is also enabled.
因此我们如果记录了备份命令的标准输出,那么可以从标准输出来判断pg_basebackup是否正常结束。
pg_basebackup xxxx >log 2>&1
或
pg_basebackup xxxx && echo "success" > log
备份日志输出到日志文件,如果日志文件中包含base backup completed的输出,则表示备份成功。
小结
通过本文提到的方法,可以在异步调用pg_basebackup时,判定pg_basebackup是否正常结束。
否则,用户在调用pg_basebackup超时后,无法得知其任务状态,只能删除备份的目标目录(否则会报dir already exists ERROR
),重新执行pg_basebackup。对于大实例,可能永远也执行不成功。
参考
man pg_basebackup
src/bin/pg_basebackup/pg_basebackup.c