openGauss源码解析(212)
openGauss源码解析:备份恢复机制(3)
10.2.3 gs_probackup备份恢复流程
gs_probackup工具在备份之前需要先进行备份目录初始化,然后进行数据库实例的全量备份,在全量备份的基础上才能进行增量备份。类似地,增量恢复也必须以某个全量备份为基础进行恢复。gs_probackup除了支持本地备份外,也支持通过SSH进行远程备份。下面是几个主要的步骤。
(1) 初始化备份目录。在指定的目录下创建backups/和wal/子目录,分别用于存放备份文件和WAL文件,代码如下:
gs_probackup init -B backup_dir
(2) 初始化一个数据库实例的备份,代码如下:
gs_probackup add-instance -B backup_dir -D data_dir --instance instance_name [remote_options]
(3) 创建指定实例的备份。在进行增量备份之前,必须至少创建一次全量备份。全量还是增量由-b backup_mode参数控制,FULL表示创建全量备份,PTRACK表示创建PTRACK增量备份,代码如下:
gs_probackup backup -B backup_dir --instance instance_name -b backup_mode
(4) 从指定实例的备份中恢复数据,代码如下:
gs_probackup restore -B backup_dir --instance instance_name -i backup_id
如果进行远程备份和恢复,需要初始化备份目录和初始化一个数据库实例的备份,第一步、第二步和本地备份恢复是相同的,执行上文中的(1)和(2)即可。但第三步和第四步需要使用SSH的远程连接信息进行备份和恢复,步骤如下所示。
(1) 远程备份,代码如下:
gs_probackup backup -B backup_dir -b FULL --stream --instance=instance_name --remote-user=remote_user --remote-host=ip --remote-port=remote_port -d db -p port -U user
(2) 远程恢复,代码如下:
gs_probackup restore -B backup_dir --instance=instance_name --remote-user=remote_user --remote-host=ip --remote-port=remote_port --incremental-mode=checksum
下面介绍每个处理函数的详细实现。
(1) init命令的处理函数是do_init,在do_init函数中。
① 首先检查命令行输入的备份路径backup_dir是否为空目录,要求必须为空目录。如果backup_dir不存在,则创建。
② 在backup_dir下创建backups子目录,创建wal子目录。
(2) add-instance的处理函数为do_add_instance,在do_add_instance处理函数中。
① 创建backup_dir/backups/instance_name子目录,创建backup_dir/wal/instance_name子目录。
② 获取实例备份参数信息,包括system_identifier,xlog_seg_size,remote.host,remote.proto,remote.port,remote.path,remote.user,remote.ssh_options,remote.ssh_config等,通过调用函数do_set_config把这些实例备份信息写到backup_path/backups/instance_name/pg_probackup.conf配置文件中。
(3) backup的处理函数为do_backup,do_backup根据参数backup_mode是FULL还是PTRACK进行全量或者增量备份。全量备份和增量备份基本流程是一样的,唯一的区别是全量备份拷贝全部数据文件,增量备份只拷贝自上次备份以来的脏数据页。函数的处理流程如下。
① 调用pgNodeInit初始化备份数据库服务器节点的信息。
② 设置备份状态为BACKUP_STATUS_RUNNING和其他备份元数据,包括备份时间、当前版本、压缩算法、压缩级别和外部目录地址。
③ 调用pgBackupCreateDir创建备份路径,备份路径由pgBackupGetPath构造,路径为backup_dir/backups/instance_name/base36enc(backup->start_time),同时创建外部目录的备份地址,地址为backup_dir/backups/instance_name/ extern_direc。
④ 备份元数据写入到backup.control控制文件中。
⑤ 调用pgdata_basic_setup创建到数据库服务器的连接,检查校验备份工具的block_size、wal_block_size,checksum_version等和数据库服务器的版本是兼容的。调用check_system_identifiers校验系统标识符system_identifier是一致的。检查数据库服务器的ptrack版本是兼容的,并且开关是打开的。
⑥ 调用add_note把备份描述信息添加到备份元数据中。
⑦ 调用do_backup_instance进行数据库实例数据备份。
⑧ 更新备份元数据中的备份结束时间,备份状态为BACKUP_STATUS_DONE。更新备份的留存策略ttl或者expire_time。
⑨ 如果需要校验备份,则调用pgBackupValidate对备份数据进行校验。
⑩ 最后如果需要删除过期的备份或者合并备份,则调用do_retention把过期的备份删除。
(4) restore的处理函数为do_restore_or_validate,函数的处理流程如下。
① 检查如果data目录不为空,看是否为增量恢复,并且当前的增量和路径中存在的数据是否兼容。首先检查两者的system_identifier标识符是否一致,如果不一致,则恢复失败。然后检查目录中是否有备份标签文件,如果存在,则恢复失败。
② 调用catalog_get_backup_list获取实例的所有备份。在catalog_get_backup_list函数中,遍历实例所有的backup.control文件,获取所有backup_id,并且根据backup_id排序。所有增量备份和他们的祖先连接起来,备份元数据有一个parent_backup,指向的就是父备份ID。
/* Link incremental backups with their ancestors.*/
for (i = 0; i < parray_num(backups); i++)
{
pgBackup *curr = parray_get(backups, i);
pgBackup **ancestor;
pgBackup key;
if (curr->backup_mode == BACKUP_MODE_FULL)
continue;
key.start_time = curr->parent_backup;
ancestor = (pgBackup **) parray_bsearch(backups, &key,
pgBackupCompareIdDesc);
if (ancestor)
curr->parent_backup_link = *ancestor;
}
③ 在备份列表中,查找满足恢复条件的备份。如果指定了target_backup_id则根据backup_id进行匹配。如果指定了pgRecoveryTarget,则根据pgRecoveryTarget进行匹配,判断函数为satisfy_recovery_target。
④ 如果找到的备份是全量备份,那么当前backup_id就是满足要求的。如果找到的备份是增量备份,需要遍历整个增量备份链表查找之前所有备份都是正常的。
⑤ 检查表空间映射是正常的。
⑥ 如果是INCR_LSN恢复,确定恢复链中的恢复位置。
⑦ 如果恢复前需要验证文件正确性,则调用pgBackupValidate和validate_wal验证数据文件和日志文件正确性。
⑧ 调用restore_chain根据备份链进行恢复。
⑨ 根据传入的恢复参数调用create_recovery_conf创建recovery.conf恢复文件。整个恢复结束。
其他的一些流程处理如下。
(5) help的help_pg_probackup和help_command,这两个函数的处理都在help.cpp中。
① help_pg_probackup命令没有输入参数,就是打印整个工具的命令行使用帮助信息。
② help_command(char *command)有一个输入参数command,根据command参数指定的子命令分别调用相应子命令的帮助处理函数。
(6) del-instance删除实例的处理函数为do_delete_instance,在do_delete_instance处理函数中。
① 调用catalog_get_backup_list获取实例。backup_dir/backups/instance_name子目录下的所有数据备份。遍历删除这些数据备份。
② 删除backup_dir/wal/instance_name子目录下的所有WAL日志文件。
③ 删除实例备份配置文件backup_dir/backups/instance_name/pg_probackup.conf。
④ 删除实例backup_dir/backups/instance_name子目录本身,删除backup_path/wal/instance_name子目录本身。