千家信息网

PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么

发表于:2024-09-30 作者:千家信息网编辑
千家信息网最后更新 2024年09月30日,这篇文章主要介绍"PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么",在日常操作中,相信很多人在PostgreSQL在响应客户端发出备份命令pg_basebackup时
千家信息网最后更新 2024年09月30日PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么

这篇文章主要介绍"PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么",在日常操作中,相信很多人在PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、数据结构

basebackup_options
pg_basebackup的选项,在数据库服务器解析为该数据结构.

typedef struct{  //备份的标签    const char *label;    //是否显示进度    bool        progress;    //是否执行快速fast checkpoint?    bool        fastcheckpoint;    //nowait?    bool        nowait;    //是否包含wal data    bool        includewal;    //    uint32      maxrate;    //是否包含表空间映射文件?    bool        sendtblspcmapfile;} basebackup_options;

二、源码解读

数据库服务器接收到请求,postmaster启动新的postgres进程响应此请求,此进程被视为walsender,标记am_walsender设置为T,在PostgresMain函数中,将执行以下逻辑:

...  for (;;)//主循环  {    ...    switch (firstchar)    {      case 'Q':     /* simple query */        {          if (am_walsender)          {            //如为WAL sender,执行exec_replication_command            if (!exec_replication_command(query_string))              exec_simple_query(query_string);            ......

调用exec_replication_command函数,执行相关命令.该函数会调用SendBaseBackup函数执行具体的实现逻辑,其中重点的实现函数是sendFileWithContent/sendDir.
1.sendFileWithContent函数用于发送backup_label等文件到客户端
pq_putmessage发送消息,'d'的消息类型表示CopyData.

static voidsendFileWithContent(const char *filename, const char *content){    struct stat statbuf;    int         pad,                len;    len = strlen(content);    /*     * Construct a stat struct for the backup_label file we're injecting in     * the tar.     */    /* Windows doesn't have the concept of uid and gid */#ifdef WIN32    statbuf.st_uid = 0;    statbuf.st_gid = 0;#else    statbuf.st_uid = geteuid();    statbuf.st_gid = getegid();#endif    statbuf.st_mtime = time(NULL);    statbuf.st_mode = pg_file_create_mode;    statbuf.st_size = len;    _tarWriteHeader(filename, NULL, &statbuf, false);    /* Send the contents as a CopyData message */    pq_putmessage('d', content, len);    /* Pad to 512 byte boundary, per tar format requirements */    pad = ((len + 511) & ~511) - len;    if (pad > 0)    {        char        buf[512];        MemSet(buf, 0, pad);        pq_putmessage('d', buf, pad);    }}

2.sendDir遍历文件目录,调用sendFile发送到客户端
递归遍历数据库目录,调用sendFile发送文件

...            if (!sizeonly)                sent = sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf,                                true, isDbDir ? pg_atoi(lastDir + 1, sizeof(Oid), 0) : InvalidOid);            if (sent || sizeonly)            {                /* Add size, rounded up to 512byte block */                size += ((statbuf.st_size + 511) & ~511);                size += 512;    /* Size of the header of the file */            }...

sendFile发送相应的文件内容到客户端

...    while ((cnt = fread(buf, 1, Min(sizeof(buf), statbuf->st_size - len), fp)) > 0)    {      ...       /* Send the chunk as a CopyData message */        if (pq_putmessage('d', buf, cnt))            ereport(ERROR,                    (errmsg("base backup could not send data, aborting backup")));        ...    }

三、跟踪分析

客户端启动pg_basebackup

[xdb@localhost ~]$ pg_basebackup -h 192.168.26.25 -U replicator -p 5432 -D /data/backup -P -Xs -RPassword:

跟踪postmaster,设置跟踪子进程

(gdb) set follow-fork-mode child(gdb) b PostgresMain

客户端输入密码后,进入断点,在执行BASE_BACKUP命令前,首先会执行SHOW data_directory_mode/SHOW wal_segment_size/IDENTIFY_SYSTEM三个命令,然后再执行BASE_BACKUP命令

...(gdb) p input_message$2 = {data = 0x20a1d78 "SHOW data_directory_mode", len = 25, maxlen = 1024, cursor = 0}...(gdb) p input_message$4 = {data = 0x20a1d78 "SHOW wal_segment_size", len = 22, maxlen = 1024, cursor = 0}...(gdb) p input_message$5 = {data = 0x20a1d78 "IDENTIFY_SYSTEM", len = 16, maxlen = 1024, cursor = 0}...(gdb) p input_message$7 = {data = 0x20a1d78 "BASE_BACKUP LABEL 'pg_basebackup base backup' PROGRESS   NOWAIT   ", len = 67, maxlen = 1024,   cursor = 0}...

跟踪SendBaseBackup

(gdb) b SendBaseBackup...4178              if (!exec_replication_command(query_string))(gdb) stepexec_replication_command (cmd_string=0x20a1d78 "BASE_BACKUP LABEL 'pg_basebackup base backup' PROGRESS   NOWAIT   ")    at walsender.c:14381438    if (got_STOPPING)1521        SendBaseBackup((BaseBackupCmd *) cmd_node);...

进入SendBaseBackup

(gdb) cContinuing.[New process 1811][Thread debugging using libthread_db enabled]Using host libthread_db library "/lib64/libthread_db.so.1".[Switching to Thread 0x7f46389b58c0 (LWP 1811)]Breakpoint 1, SendBaseBackup (cmd=0x2137da8) at basebackup.c:762762   parse_basebackup_options(cmd->options, &opt);(gdb) n764   WalSndSetState(WALSNDSTATE_BACKUP);(gdb) p opt$1 = {label = 0x2137760 "pg_basebackup base backup", progress = true, fastcheckpoint = false, nowait = true,   includewal = false, maxrate = 0, sendtblspcmapfile = false}

实际执行backup的是函数perform_base_backup

...(gdb) 775   perform_base_backup(&opt);(gdb) stepperform_base_backup (opt=0x7ffc96573180) at basebackup.c:232

执行sendXXX

320       if (ti->path == NULL)(gdb) 325         sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data);(gdb) p *labelfile$4 = {  data = 0x2138a50 "START WAL LOCATION: 0/66000028 (file 0000001", '0' , "66)\nCHECKPOINT LOCATION: 0/66000060\nBACKUP METHOD: streamed\nBACKUP FROM: master\nSTART TIME: 2019-03-26 17:05:45 CST\nLABEL: pg_basebackup base"...,   len = 227, maxlen = 1024, cursor = 0}(gdb) n331         if (tblspc_map_file && opt->sendtblspcmapfile)(gdb) 337           sendDir(".", 1, false, tablespaces, true);(gdb) 340         if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)(gdb) 345         sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false);(gdb) 356       if (opt->includewal && ti->path == NULL)(gdb) 361         pq_putemptymessage('c');  /* CopyDone */(gdb) 309     foreach(lc, tablespaces)(gdb) 364     endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);(gdb) 366   PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);(gdb) 369   if (opt->includewal)(gdb) 605   SendXlogRecPtrResult(endptr, endtli);(gdb) 607   if (total_checksum_failures)(gdb) 623 }(gdb) SendBaseBackup (cmd=0x2137da8) at basebackup.c:776776 }(gdb) exec_replication_command (cmd_string=0x20a1d78 "BASE_BACKUP LABEL 'pg_basebackup base backup' PROGRESS   NOWAIT   ")    at walsender.c:15221522        break;(gdb) cContinuing.[Inferior 2 (process 1811) exited normally](gdb)

到此,关于"PostgreSQL在响应客户端发出备份命令pg_basebackup时做了什么"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0