干运维这行,逻辑备份和物理备份我都用,但说句心里话,真正能在生产环境里扛事的,还得是物理备份。逻辑备份导出的是 SQL 语句,数据量一大就慢得让人抓狂,而且没法做时间点恢复。物理备份不一样,它直接拷数据文件,配上 WAL 归档日志,想恢复到过去哪一秒都行。这篇文章我想把金仓数据库(KingbaseES)的物理备份彻底讲明白,核心工具就是sys_rman。我会从环境准备一路演练到全量、差异、增量备份,再到模拟误删之后怎么救回来,最后还会聊一个特别揪心的真实场景:有人手滑用旧备份把生产库覆盖了,这种时候该怎么抢救。内容都是实操验证过的,版本基于 V9R3C18。一、物理备份和逻辑备份,到底差在哪先把概念厘清。sys_rman是金仓提供的物理备份恢复工具,它干的事是把数据库的数据文件做物理拷贝,同时归档 WAL(Write-Ahead Logging)日志。靠着这两样东西,它支持全量备份、差异备份和文件级增量备份三种策略,还能做基于时间点的恢复,也就是我们常说的 PITR(Point-In-Time Recovery)。PITR 是物理备份最值钱的能力。它意味着你可以把数据库精确地拉回到过去任意一个历史时刻,这在应对误操作时几乎是救命稻草。后面的实战我会专门演示这一点。二、动手前的环境准备开始之前,有几样东西得确认好。我的实验环境用的是 MySQL 兼容模式实例,环境变量是这么配的:cat/home/kingbase/.bashrcEOF export KINGBASE_DATABASEtest export KINGBASE_USERsystem export KINGBASE_HOME/KingbaseES/V9/Server export KINGBASE_DATA/KingbaseES/kes_shanjia export PATH\$KINGBASE_HOME/bin:\$PATHexport KINGBASE_PORT54321 EOF接着确认两件事。第一,数据库实例正常运行:ksql-dkingbase-Usystem-p54321-cSELECT sys_is_in_recovery();第二,也是物理备份的前提条件,必须开启归档模式。这一步千万不能跳过,因为没有归档日志,PITR 就无从谈起:ksql-Usystem-dtest-cshow archive_mode;show archive_command三、用 sys_backup.sh 初始化备份环境sys_rman的备份环境不是手动一点点配的,金仓提供了sys_backup.sh脚本帮你一键初始化。但脚本背后的配置文件sys_backup.conf才是关键,这里的参数决定了你整套备份策略长什么样。我把几个核心参数挑出来说说:_target_db_stylesingle # 单机环境,集群另说 _one_db_ip192.168.40.128 # 要备份的主机 IP _repo_ip192.168.40.128 # 备份文件存放位置的 IP _stanza_namekingbase # 标签名,后面命令都要用到 _os_user_namekingbase # 运行 kes 的 OS 用户 _repo_path/data/kesbackup/rman # 备份文件和归档日志的存放目录 _repo_retention_full_count5 # 备份集保留策略,保留 5 份 _crond_full_days7 # 每 7 天做一次全量 _crond_diff_days0 # 0 表示不做差异备份 _crond_incr_days1 # 每天做一次增量 _single_data_dir/KingbaseES/kes_shanjia # 数据库目录路径 _single_bin_dir/KingbaseES/V9/Server/bin # 数据库 bin 目录 _single_db_port54321 # 监听端口 _compress_typenone # 压缩类型这里我想多嘴一句_stanza_name。stanza 这个概念在sys_rman里贯穿始终,它本质上是一个备份配置单元的标签,后面几乎每条命令都要带--stanzakingbase。配置改好后执行初始化:sys_backup.sh init四、全量备份与恢复演练环境就绪,先做一次全量备份。全量是一切的基础,差异和增量都得依附在它上面:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup备份完用info命令看一眼备份集信息,确认成功:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase info接下来模拟一场灾难。先建表插数据,记下当前时间,这个时间点很重要,后面恢复要靠它:CREATETABLEtest_backup(idint,namevarchar(50));INSERTINTOtest_backupVALUES(1,test_full_backup);SELECTnow();然后手滑,把表删了:DROPTABLEtest_backup;恢复流程是这样的。先停库,把原数据目录改名留底(注意不是删,是重命名,给自己留条后路):sys_ctl stopmv/KingbaseES/kes_shanjia /KingbaseES/kes_shanjia.bak执行还原:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase restore五、PITR 的暂停机制:这是安全设计,不是 Bug启动数据库后,你去翻日志,会看到一段让初学者很困惑的输出:LOG: 在0/14009788上已到达一致性恢复状态 LOG: 恢复停止在事务 950 提交之前, 时间 2026-06-26 01:44:05.50624508 LOG: 恢复操作已暂停 HINT: 执行sys_wal_replay_resume()继续。 LOG: 数据库系统准备接受只读请求的连接数据库恢复到了目标时间点,但它没有直接进入读写状态,而是停在只读模式,提示你恢复操作已暂停。我第一次见这个的时候也愣了一下,以为出错了。后来才明白,这恰恰是金仓设计上的精巧之处。这个暂停窗口,是把最后的审查权交给了 DBA。你可以先在只读模式下慢慢查数据,确认恢复的时间点对不对、数据是不是你要的那个状态,确认无误了再提交。这相当于在数据真正落盘前给你一道保险,防止因为恢复点选错而造成二次数据丢失。确认没问题后,执行这条命令完成最终提权,数据库才会进入读写模式:SELECTsys_wal_replay_resume();恢复完别忘了善后。kingbase.auto.conf里那些还原参数得清理掉,否则下次启动会出岔子:vi/KingbaseES/kes_shanjia/kingbase.auto.conf# 删除 restore_command、recovery_target_time、# recovery_target_action 以及其他 recovery_target_* 参数清理后重启,再做一次新的全量备份,让一切回归正轨:sys_ctl restart sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup六、差异备份与增量备份:理解备份链全量讲完,该聊差异和增量了。这两者的区别和依赖关系,是物理备份里最需要建立直觉的部分。先做一个全量作为基础,记下它的备份集名称,比如20260626-132418F,后面合并要用:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup插一条新数据,做差异备份。差异备份记录的是相对于上一次全量的变化,所以它的体积明显比全量小:INSERTINTOtest_backupVALUES(2,after_full_backup_diff);sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typediff backup再插一条,做文件增量备份。增量备份的backup reference list会指向它依赖的全量备份集:INSERTINTOtest_backupVALUES(3,after_diff_backup_incr);sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typeincr backup现在到了关键的验证环节。删表,清空数据目录,然后还原(默认还原最新备份集):sys_ctl stoprm-rf/KingbaseES/kes_shanjia/*rm-rf/KingbaseES/kes_shanjia/.wallet sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase restore启动后查一下,你会发现 3 条数据全回来了:全量的 1 条、差异的 1 条、增量的 1 条。这个结果直观地说明了备份链的含义:一个增量备份能不能用,完全取决于它前面的全量以及中间所有的差异/增量是否完整。任何一环断了,整条链就废了。这也是为什么备份策略必须和 WAL 日志管理策略紧紧绑在一起。七、永久增量备份:用合并平衡成本与效率纯增量备份省时间省空间,但有个硬伤:恢复链会越来越长,链子一长,恢复效率就直线下降。金仓的解法是永久增量备份,核心是merge操作,把多个历史备份集压实成一个新的全量。手动合并是这样的:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase\--set20260626-132418F_20260626-140541I--merge_actionmerge-and-delete merge这里--merge_action有两个常用取值得分清:merge-and-delete是合并后把旧的全量备份集移除,merge-no-delete是合并但保留旧全量。你也可以在做增量备份的时候顺手合并,一步到位:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase\--typeincr--merge_actionmerge-and-delete backup合并之后,增量备份集就变成了一个新的全量备份集,旧的基础全量被移除了。这么一来,你既享受了增量备份的短平快,又在恢复时拥有了全量备份的高可靠性。对于存储紧张、RTO 要求严格的业务来说,这几乎是最优解。至于定时自动备份,改好sys_backup.conf后,用脚本初始化并启动,再用crontab -l验证任务生效就行:sh/KingbaseES/V9/.../Server/bin/sys_backup.sh initsh/KingbaseES/V9/.../Server/bin/sys_backup.sh startcrontab-l八、高危场景:误用旧备份覆盖了生产库,怎么救前面都是常规演练,现在说一个真正让人后背发凉的事故。有运维同学没停业务、没备份当前数据,直接把 7 天前的历史备份集恢复到了正在运行的生产库上,结果当天所有新增和修改的数据全被旧数据覆盖了。物理恢复是覆盖式操作,它会直接替换 data 目录下的文件,常规的撤销手段统统无效。这种时候,抢救能不能成功,取决于你接下来几分钟的动作。两条黄金原则,务必死守:第一,禁止重启数据库。没重启之前,数据库内存里还缓存着最新的事务数据,磁盘上也残留着没被完全覆盖的数据块,这些是抢救的唯一依据。一旦重启,覆盖结果就被固化,最新数据彻底没了。第二,禁止写入任何数据。立刻暂停所有业务写入和运维操作,避免新数据把磁盘上的原始残留块也覆盖掉。抢救步骤大致是这样:先冻结现场,关闭业务接口禁止写入,但保持数据库进程运行,不重启不关闭。然后快速打包当前的 data 目录,把现场环境留存下来,防止二次损坏:su- kingbasetar-zcvf/data/kb_data_error_bak.tar.gz /home/kingbase/KingbaseES-V9R2/data接着趁数据还没固化,用逻辑导出工具把内存里缓存的最新业务数据抢出来:ks_dump-Usystem-d业务库名-f/data/latest_data_backup.sql之后再走精准恢复的正路:停库,重建一个纯净的空数据目录避免残留文件冲突,然后用 PITR 恢复到误操作前一分钟:sys_rman --backup-path /data/kb_backup restore--time2026-06-17 10:29:00最后,把第三步抢出来的增量数据导回恢复后的库,业务数据就完整还原了。九、把误操作挡在门外:标准化流程这种事故,事后抢救再漂亮也是被动的,真正的功夫在事前预防。我总结几条生产环境必须强制执行的规矩:恢复前必须先备份当前生产数据,留个兜底,这是底线中的底线。所有恢复脚本和命令,先在测试环境跑通再上生产。物理恢复优先恢复到新目录,验证数据无误后再替换生产库,绝不直接覆盖。生产库的恢复操作,必须双人复核命令、备份集和时间点,确认无误才执行。写在最后走完sys_rman这一整套流程,我最大的感受是:可靠的数据保护从来不是靠某个强大的工具单打独斗,而是靠一套规范、可复制的操作流程。从环境准备到清理还原参数,每一环都不容有失。物理备份恢复是高危操作,覆盖式恢复不可逆。但只要你建立起备份链和恢复点的概念,理解了 PITR 暂停机制的良苦用心,再加上严格的标准化流程,就能在DROP TABLE这样的致命误操作面前从容地把数据救回来。我的建议永远是那句老话:所有操作先在非生产环境演练。一次成功的恢复,背后是无数次枯燥的备份演练。功夫在日常,这话用在数据库运维上,再贴切不过了。
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
发布时间:2026/6/28 6:22:42
干运维这行,逻辑备份和物理备份我都用,但说句心里话,真正能在生产环境里扛事的,还得是物理备份。逻辑备份导出的是 SQL 语句,数据量一大就慢得让人抓狂,而且没法做时间点恢复。物理备份不一样,它直接拷数据文件,配上 WAL 归档日志,想恢复到过去哪一秒都行。这篇文章我想把金仓数据库(KingbaseES)的物理备份彻底讲明白,核心工具就是sys_rman。我会从环境准备一路演练到全量、差异、增量备份,再到模拟误删之后怎么救回来,最后还会聊一个特别揪心的真实场景:有人手滑用旧备份把生产库覆盖了,这种时候该怎么抢救。内容都是实操验证过的,版本基于 V9R3C18。一、物理备份和逻辑备份,到底差在哪先把概念厘清。sys_rman是金仓提供的物理备份恢复工具,它干的事是把数据库的数据文件做物理拷贝,同时归档 WAL(Write-Ahead Logging)日志。靠着这两样东西,它支持全量备份、差异备份和文件级增量备份三种策略,还能做基于时间点的恢复,也就是我们常说的 PITR(Point-In-Time Recovery)。PITR 是物理备份最值钱的能力。它意味着你可以把数据库精确地拉回到过去任意一个历史时刻,这在应对误操作时几乎是救命稻草。后面的实战我会专门演示这一点。二、动手前的环境准备开始之前,有几样东西得确认好。我的实验环境用的是 MySQL 兼容模式实例,环境变量是这么配的:cat/home/kingbase/.bashrcEOF export KINGBASE_DATABASEtest export KINGBASE_USERsystem export KINGBASE_HOME/KingbaseES/V9/Server export KINGBASE_DATA/KingbaseES/kes_shanjia export PATH\$KINGBASE_HOME/bin:\$PATHexport KINGBASE_PORT54321 EOF接着确认两件事。第一,数据库实例正常运行:ksql-dkingbase-Usystem-p54321-cSELECT sys_is_in_recovery();第二,也是物理备份的前提条件,必须开启归档模式。这一步千万不能跳过,因为没有归档日志,PITR 就无从谈起:ksql-Usystem-dtest-cshow archive_mode;show archive_command三、用 sys_backup.sh 初始化备份环境sys_rman的备份环境不是手动一点点配的,金仓提供了sys_backup.sh脚本帮你一键初始化。但脚本背后的配置文件sys_backup.conf才是关键,这里的参数决定了你整套备份策略长什么样。我把几个核心参数挑出来说说:_target_db_stylesingle # 单机环境,集群另说 _one_db_ip192.168.40.128 # 要备份的主机 IP _repo_ip192.168.40.128 # 备份文件存放位置的 IP _stanza_namekingbase # 标签名,后面命令都要用到 _os_user_namekingbase # 运行 kes 的 OS 用户 _repo_path/data/kesbackup/rman # 备份文件和归档日志的存放目录 _repo_retention_full_count5 # 备份集保留策略,保留 5 份 _crond_full_days7 # 每 7 天做一次全量 _crond_diff_days0 # 0 表示不做差异备份 _crond_incr_days1 # 每天做一次增量 _single_data_dir/KingbaseES/kes_shanjia # 数据库目录路径 _single_bin_dir/KingbaseES/V9/Server/bin # 数据库 bin 目录 _single_db_port54321 # 监听端口 _compress_typenone # 压缩类型这里我想多嘴一句_stanza_name。stanza 这个概念在sys_rman里贯穿始终,它本质上是一个备份配置单元的标签,后面几乎每条命令都要带--stanzakingbase。配置改好后执行初始化:sys_backup.sh init四、全量备份与恢复演练环境就绪,先做一次全量备份。全量是一切的基础,差异和增量都得依附在它上面:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup备份完用info命令看一眼备份集信息,确认成功:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase info接下来模拟一场灾难。先建表插数据,记下当前时间,这个时间点很重要,后面恢复要靠它:CREATETABLEtest_backup(idint,namevarchar(50));INSERTINTOtest_backupVALUES(1,test_full_backup);SELECTnow();然后手滑,把表删了:DROPTABLEtest_backup;恢复流程是这样的。先停库,把原数据目录改名留底(注意不是删,是重命名,给自己留条后路):sys_ctl stopmv/KingbaseES/kes_shanjia /KingbaseES/kes_shanjia.bak执行还原:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase restore五、PITR 的暂停机制:这是安全设计,不是 Bug启动数据库后,你去翻日志,会看到一段让初学者很困惑的输出:LOG: 在0/14009788上已到达一致性恢复状态 LOG: 恢复停止在事务 950 提交之前, 时间 2026-06-26 01:44:05.50624508 LOG: 恢复操作已暂停 HINT: 执行sys_wal_replay_resume()继续。 LOG: 数据库系统准备接受只读请求的连接数据库恢复到了目标时间点,但它没有直接进入读写状态,而是停在只读模式,提示你恢复操作已暂停。我第一次见这个的时候也愣了一下,以为出错了。后来才明白,这恰恰是金仓设计上的精巧之处。这个暂停窗口,是把最后的审查权交给了 DBA。你可以先在只读模式下慢慢查数据,确认恢复的时间点对不对、数据是不是你要的那个状态,确认无误了再提交。这相当于在数据真正落盘前给你一道保险,防止因为恢复点选错而造成二次数据丢失。确认没问题后,执行这条命令完成最终提权,数据库才会进入读写模式:SELECTsys_wal_replay_resume();恢复完别忘了善后。kingbase.auto.conf里那些还原参数得清理掉,否则下次启动会出岔子:vi/KingbaseES/kes_shanjia/kingbase.auto.conf# 删除 restore_command、recovery_target_time、# recovery_target_action 以及其他 recovery_target_* 参数清理后重启,再做一次新的全量备份,让一切回归正轨:sys_ctl restart sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup六、差异备份与增量备份:理解备份链全量讲完,该聊差异和增量了。这两者的区别和依赖关系,是物理备份里最需要建立直觉的部分。先做一个全量作为基础,记下它的备份集名称,比如20260626-132418F,后面合并要用:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typefull backup插一条新数据,做差异备份。差异备份记录的是相对于上一次全量的变化,所以它的体积明显比全量小:INSERTINTOtest_backupVALUES(2,after_full_backup_diff);sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typediff backup再插一条,做文件增量备份。增量备份的backup reference list会指向它依赖的全量备份集:INSERTINTOtest_backupVALUES(3,after_diff_backup_incr);sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase--typeincr backup现在到了关键的验证环节。删表,清空数据目录,然后还原(默认还原最新备份集):sys_ctl stoprm-rf/KingbaseES/kes_shanjia/*rm-rf/KingbaseES/kes_shanjia/.wallet sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase restore启动后查一下,你会发现 3 条数据全回来了:全量的 1 条、差异的 1 条、增量的 1 条。这个结果直观地说明了备份链的含义:一个增量备份能不能用,完全取决于它前面的全量以及中间所有的差异/增量是否完整。任何一环断了,整条链就废了。这也是为什么备份策略必须和 WAL 日志管理策略紧紧绑在一起。七、永久增量备份:用合并平衡成本与效率纯增量备份省时间省空间,但有个硬伤:恢复链会越来越长,链子一长,恢复效率就直线下降。金仓的解法是永久增量备份,核心是merge操作,把多个历史备份集压实成一个新的全量。手动合并是这样的:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase\--set20260626-132418F_20260626-140541I--merge_actionmerge-and-delete merge这里--merge_action有两个常用取值得分清:merge-and-delete是合并后把旧的全量备份集移除,merge-no-delete是合并但保留旧全量。你也可以在做增量备份的时候顺手合并,一步到位:sys_rman--config/data/kesbackup/rman/sys_rman.conf--stanzakingbase\--typeincr--merge_actionmerge-and-delete backup合并之后,增量备份集就变成了一个新的全量备份集,旧的基础全量被移除了。这么一来,你既享受了增量备份的短平快,又在恢复时拥有了全量备份的高可靠性。对于存储紧张、RTO 要求严格的业务来说,这几乎是最优解。至于定时自动备份,改好sys_backup.conf后,用脚本初始化并启动,再用crontab -l验证任务生效就行:sh/KingbaseES/V9/.../Server/bin/sys_backup.sh initsh/KingbaseES/V9/.../Server/bin/sys_backup.sh startcrontab-l八、高危场景:误用旧备份覆盖了生产库,怎么救前面都是常规演练,现在说一个真正让人后背发凉的事故。有运维同学没停业务、没备份当前数据,直接把 7 天前的历史备份集恢复到了正在运行的生产库上,结果当天所有新增和修改的数据全被旧数据覆盖了。物理恢复是覆盖式操作,它会直接替换 data 目录下的文件,常规的撤销手段统统无效。这种时候,抢救能不能成功,取决于你接下来几分钟的动作。两条黄金原则,务必死守:第一,禁止重启数据库。没重启之前,数据库内存里还缓存着最新的事务数据,磁盘上也残留着没被完全覆盖的数据块,这些是抢救的唯一依据。一旦重启,覆盖结果就被固化,最新数据彻底没了。第二,禁止写入任何数据。立刻暂停所有业务写入和运维操作,避免新数据把磁盘上的原始残留块也覆盖掉。抢救步骤大致是这样:先冻结现场,关闭业务接口禁止写入,但保持数据库进程运行,不重启不关闭。然后快速打包当前的 data 目录,把现场环境留存下来,防止二次损坏:su- kingbasetar-zcvf/data/kb_data_error_bak.tar.gz /home/kingbase/KingbaseES-V9R2/data接着趁数据还没固化,用逻辑导出工具把内存里缓存的最新业务数据抢出来:ks_dump-Usystem-d业务库名-f/data/latest_data_backup.sql之后再走精准恢复的正路:停库,重建一个纯净的空数据目录避免残留文件冲突,然后用 PITR 恢复到误操作前一分钟:sys_rman --backup-path /data/kb_backup restore--time2026-06-17 10:29:00最后,把第三步抢出来的增量数据导回恢复后的库,业务数据就完整还原了。九、把误操作挡在门外:标准化流程这种事故,事后抢救再漂亮也是被动的,真正的功夫在事前预防。我总结几条生产环境必须强制执行的规矩:恢复前必须先备份当前生产数据,留个兜底,这是底线中的底线。所有恢复脚本和命令,先在测试环境跑通再上生产。物理恢复优先恢复到新目录,验证数据无误后再替换生产库,绝不直接覆盖。生产库的恢复操作,必须双人复核命令、备份集和时间点,确认无误才执行。写在最后走完sys_rman这一整套流程,我最大的感受是:可靠的数据保护从来不是靠某个强大的工具单打独斗,而是靠一套规范、可复制的操作流程。从环境准备到清理还原参数,每一环都不容有失。物理备份恢复是高危操作,覆盖式恢复不可逆。但只要你建立起备份链和恢复点的概念,理解了 PITR 暂停机制的良苦用心,再加上严格的标准化流程,就能在DROP TABLE这样的致命误操作面前从容地把数据救回来。我的建议永远是那句老话:所有操作先在非生产环境演练。一次成功的恢复,背后是无数次枯燥的备份演练。功夫在日常,这话用在数据库运维上,再贴切不过了。