這篇文章主要介紹“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 void
sendFileWithContent(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 -R Password:
跟蹤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) step exec_replication_command (cmd_string=0x20a1d78 "BASE_BACKUP LABEL 'pg_basebackup base backup' PROGRESS NOWAIT ") at walsender.c:1438 1438 if (got_STOPPING) 1521 SendBaseBackup((BaseBackupCmd *) cmd_node); ...
進入SendBaseBackup
(gdb) c
Continuing.
[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:762
762 parse_basebackup_options(cmd->options, &opt);
(gdb) n
764 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) step perform_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' <repeats 15 times>, "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) n
331 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:776
776 }
(gdb)
exec_replication_command (cmd_string=0x20a1d78 "BASE_BACKUP LABEL 'pg_basebackup base backup' PROGRESS NOWAIT ")
at walsender.c:1522
1522 break;
(gdb) c
Continuing.
[Inferior 2 (process 1811) exited normally]
(gdb)到此,關于“PostgreSQL在響應客戶端發出備份命令pg_basebackup時做了什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。