pg_basebackup原理解析

pg_basebackup

介绍

pg_basebackup提供一个全量备份。常用来搭建流复制环境。属于物理备份。逻辑备份工具时pg_dump。参数说明:

-D:--pgdata=DIRECTORRY,接收备份的目录

-F:--format=p | t,指定输出格式,支持p(原样输出)或者t(tar格式输出)

-r:--max-rate=RATE,最大传输率(kB/s,或用前缀 k,M)

-R,--write-recovery-conf,备份后写recovery.conf文件

-s,--slot=SLOTNAME,使用的复制槽

-T:--tablespace-mapping=OLDDIR=NEWDIR,使用NEWDIR替代OLDDIR

-x:--xlog,备份开始后,启动另一个流复制连接从主库接收WAL

-X:--xlog-method=fetch| stream

   --xlogdir=XLOGDIR

-z:--gzip

-Z:--compress=0-9

--target-gp-dbid:根据给定的dbid创建表空间子目录

 

-C,--checkpoint=fast| spread

-l,--label=LABLE:设置backup label

-E,--exclude

--exclude-from=FILE

 

 

选项:

static struct optionlong_options[] = {

        {"help", no_argument, NULL,'?'},

        {"version", no_argument, NULL,'V'},

        {"pgdata", required_argument,NULL, 'D'},

        {"format", required_argument,NULL, 'F'},

        {"checkpoint",required_argument, NULL, 'c'},

        {"create-slot", no_argument,NULL, 'C'},

        {"max-rate",required_argument, NULL, 'r'},

        {"write-recovery-conf",no_argument, NULL, 'R'},

        {"slot", required_argument,NULL, 'S'},

        {"tablespace-mapping",required_argument, NULL, 'T'},

        {"wal-method",required_argument, NULL, 'X'},

        {"gzip", no_argument, NULL,'z'},

        {"compress",required_argument, NULL, 'Z'},

        {"label", required_argument,NULL, 'l'},

        {"no-clean", no_argument,NULL, 'n'},

        {"no-sync", no_argument, NULL,'N'},

        {"dbname", required_argument,NULL, 'd'},

        {"host", required_argument,NULL, 'h'},

        {"port", required_argument,NULL, 'p'},

        {"username", required_argument,NULL, 'U'},

        {"no-password", no_argument,NULL, 'w'},

        {"password", no_argument,NULL, 'W'},

        {"status-interval",required_argument, NULL, 's'},

        {"verbose", no_argument, NULL,'v'},

        {"progress", no_argument,NULL, 'P'},

        {"waldir", required_argument,NULL, 1},

        {"no-slot", no_argument, NULL,2},

        {"no-verify-checksums",no_argument, NULL, 3},

        {NULL, 0, NULL, 0}

    };

 

流程

1、上层流程

1)先对传入的参数进行互斥检测,必须指定备份路径-D,format指定t模式时才可以使用压缩级别compresslevel。仅includewal为流复制模式时才可以使用复制槽。no_slot下不使用复制槽和temp_replication_slot。create_slot即指定-C时必须使用复制槽。xlog_dir下必须使用format为p即plain模式,且必须使用绝对路径。

2)通过GetConnection函数连接主,返回连接conn

3)format为p模式下,如果-D指定的目录不存在则创建该目录,若存在,则这个目录必须为空

4)通过RetrieveWalSegSize函数得到远程WAL文件大小WalSegSz,通过执行SHOWwal_segment_size得到:

postgres=# show wal_segment_size;
-------------------------------
16MB
(1 row)

5)调用函数BaseBackup进行全量备份。


2、BaseBackup

1)如果指定-R创建recovery.conf文件,那么先在内存中产生内容:

   standby_mode=’on’

  primary_conninfo=’replication= dbname=  fallback_application_name=’

  primary_slot_name=’’

   在备份完成后,写入recovery.conf文件WriteRecoveryConf();

2)调用RunIdentifySystem向主发送IDENTIFY_SYSTEM命令,获取系统标识及时间线,例如:

psql “dbname=postgres replication=database”-c “IDENTIFY_SYSTEM;”
systemid    timeline   xlogpos  dbname
------------------+--------+----------+--------
69516718657589179 |       1| 0/80000D8| postgres
(1 row)

   主接收到命令后由函数exec_replication_command进行处理:IdentifySystem();时间线为主机的ThisTimeLineID。(这个值主上怎么更新?)

3)生成BASE BACKUP命令,并向主发送。得到wal起始位置xlogstart和起始时间线starttli,表空间个数tablespacecount和循环计算得到文件总数totalsize?

4)如果时流复制拉取,那么调用函数StartLogStreamer初始化后台进程用于接收WAL,会启动一个进程。

这里请求的开始时间线9.3及之后版本为BASE_BACKUP获取的时间线值,否则为IDENTIFY_SYSTEM获取主上当前时间线值。

StartLogStreamer(xlogstart, starttli, sysidentifier),注册流复制结构:

typedef struct
{
    PGconn    *bgconn;
    XLogRecPtr  startptr;
    char       xlog[MAXPGPATH];/* directory or tarfiledepending on mode */
    char      *sysidentifier;
    int        timeline;
} logstreamer_param;

 

param->timeline = timeline;
param->sysidentifier = sysidentifier;
param->startptr = ((uint64) hi) << 32 | lo;//xlogstart转换
//对齐文件头
param->startptr -=XLogSegmentOffset(param->startptr, WalSegSz);
param->bgconn = GetConnection();//另连接master server
replication_slot//创建复制槽
format为p模式创建archive_status目录
bgchild = fork();
if (bgchild == 0){//子进程
        /* in childprocess */
        exit(LogStreamerMain(param));
}
atexit(kill_bgchild_atexit);//父进程

5)对于每个表空间:分别根据format指定的格式拉取数据,若是t则调用ReceiveTarFile接收tar文件,否则调用ReceiveAndUnpackTarFile接收tar文件并解压。这里接收的是数据文件。

接收日志和接收数据不在同一个进程中,为流复制单独创建一个接收日志子进程,子进程接收日志开始的命令是START_REPLICATION,然后开启COPY流。

数据的话应该是BASE_BACKUP,然后开启COPY流。

6)接着根据指定的参数决定是否打印进度

7)获取wal结束位置xlogend

8)根据指定的参数决定是否打印wal end point点

9)调用waitpid等待子进程退出

10)最后将数据全部sync

 

3、LogStreamerMain

这个是一个子进程处理的内容,根据日志起始时间线及位置初始化流复制结构StreamCtl,然后调用函数ReceiveXlogStream进行流复制接收日志文件。

 

4、ReceiveXlogStream

1)首先判断时间线对应的history文件,不存在的话通过向主发送TIMELINE_HISTORY命令获取主对于history文件内容,然后写到本地。

2)向主发送START_REPLICATION命令,开始复制,调用函数HandleCopyStream处理COPY流

3)如果当前时间线的日志接收完,那么从下一个时间线开始重新接收。下一个时间线及其起始位置会由HandleCopyStream返回res中记录。下个时间线流复制开始位置会对齐到文件头位置。(也就是说总是从文件头开始复制)

4)如果返回的结果状态时PGRES_COMMAND_OK表示复制结束

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值