ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

金仓数据库逻辑备份与恢复实战:sys_dump与sys_restore避坑指南

金仓数据库逻辑备份与恢复实战:sys_dump与sys_restore避坑指南 前阵子刚处理完一起金仓数据库的紧急恢复客户在生产库上误删了一张核心业务表好在平时留了一份逻辑备份从发现到把表完整拉回来前后不到半小时。后来复盘的时候我就一直在想金仓KingbaseES数据库的逻辑备份与恢复表面上就是几条命令的事但备份格式怎么选、参数怎么配、恢复顺序有什么讲究、踩坑了怎么排查这些细节不提前过一遍真到出事故的时候是要付出代价的。这篇文章就围绕金仓数据库逻辑备份与恢复的完整实操经验展开适合一线DBA、运维工程师以及正在从Oracle、PostgreSQL迁移到金仓环境的开发同学参考争取让你看完就能直接照着搭一套可用的备份恢复方案。1. 先想清楚逻辑备份到底在备份什么1.1 逻辑备份和物理备份别再混为一谈逻辑备份本质上就是把数据库里的结构定义表、索引、视图、序列、触发器等和数据记录按照SQL文本或者特定的二进制归档格式导出来。金仓数据库自带的逻辑备份工具工作方式和PostgreSQL的pg_dump很相似导出的是一个可以重新执行的“描述文件”——你拿到这个文件在另一套空库上重跑一遍就能把结构和数据还原出来。物理备份则完全不同它直接拷贝数据库底层的物理文件比如数据目录、WAL日志、表空间文件讲究的是“文件级复制”恢复时把文件放回原位数据库就能起来。两者的差别打个比方逻辑备份像把一本书的内容重新抄写一遍物理备份像直接复印整本书。这个区别带来的直接后果就是逻辑备份的文件体积通常比物理备份小因为只包含有效数据不带页面的空闲空间但恢复速度通常比物理备份慢因为要重新执行建表语句、逐条灌数据、重建索引。搞清楚这个底层差异后面很多选择就容易做了。1.2 逻辑备份的典型应用场景这几年做金仓数据库运维我总结下来逻辑备份最常用的场景其实是这几类单表或单模式误删恢复这是最刚需的场景。某张表被DROP了物理备份如果没做日常增量恢复起来动静太大而一份当天的逻辑备份可以精准地把这张表导回来。数据迁移与环境复制从测试库抽一份数据到生产环境或者从旧版本金仓迁移到新版本逻辑备份几乎是标准操作。抽数给分析系统业务方只要某几个表的部分数据用逻辑备份工具按表、按模式导出比物理拷贝灵活得多。小规模数据库的日常兜底如果库不大每天做一次逻辑备份配合定期物理备份形成“双保险”。我不建议把逻辑备份当成唯一的容灾手段尤其是TB级以上的生产库全量逻辑备份的时间和空间成本都很高。更合理的定位是物理备份保底逻辑备份做精细化补充。1.3 金仓数据库自带的备份恢复工具一览金仓数据库KingbaseES在备份恢复这块官方提供了一套和PostgreSQL工具链逻辑相近的命令行工具我在实际环境中用得最多的三个是sys_dump逻辑备份工具负责把数据库对象和数据导出到文件。不同版本的工具名可能略有差异有的版本叫kdb_dump建议以安装目录bin/下的实际命令为准使用前先sys_dump --version确认一下。sys_restore逻辑恢复工具专门用来把sys_dump导出的自定义格式或目录格式归档文件恢复回库中。psql金仓自带的交互式命令行工具也可以直接执行纯SQL文本格式的备份文件完成恢复。这里有个容易绕晕的点sys_restore不是万能的它只能读取-Fc自定义格式和-Fd目录格式的备份文件。如果当初用的是-Fp纯SQL文本格式那恢复时就得靠psql去执行。所以备份格式的选择会直接影响恢复路径这个后面详细说。2. 逻辑备份实操命令、参数与备份策略2.1 sys_dump 基础备份命令速查先给一套可以直接抄作业的基础命令。假设金仓数据库安装在默认路径端口默认是54321超级管理员账号是system我要备份的业务库叫testdb# 纯SQL文本格式最通用 sys_dump -h 127.0.0.1 -p 54321 -U system -W -Fp -f /backup/testdb_$(date %Y%m%d).sql testdb # 自定义归档格式配合sys_restore使用支持压缩和选择性恢复 sys_dump -h 127.0.0.1 -p 54321 -U system -W -Fc -f /backup/testdb_$(date %Y%m%d).dmp testdb # 目录格式支持并发备份适合大库 sys_dump -h 127.0.0.1 -p 54321 -U system -W -Fd -j 4 -f /backup/testdb_dir testdb # 只备份某一张表 sys_dump -h 127.0.0.1 -p 54321 -U system -W -Fc -t public.order_info -f /backup/order_info.dmp testdb # 只备份数据不备份结构 sys_dump -h 127.0.0.1 -p 54321 -U system -W -Fc -a -f /backup/testdb_data.dmp testdb-W参数会让命令交互式地提示输入密码。如果写定时任务我一般更推荐用环境变量KDB_PASSWORD或者对应工具支持的密码文件方式避免密码暴露在进程列表里也更方便自动化。2.2 备份格式怎么选plain、custom还是目录格式这是判断一个金仓DBA有没有经验的分水岭。我看过不少初学者的习惯图省事直接sys_dump不加参数默认输出纯SQL文本plain格式然后扔到crontab里每天都备份。这种做法对于小库没问题但一旦库变大麻烦就来了。三种格式的核心差异我整理成了对比格式参数能否用sys_restore是否压缩支持并行适合场景纯SQL文本-Fp不能用psql执行可配合外部gzip不支持小库、跨版本迁移、需要人工阅读备份内容自定义归档-Fc能内部压缩恢复时支持-j并发日常备份首选选择性恢复方便目录格式-Fd能每个文件单独压缩备份和恢复都支持-j大库备份需要并发加速我个人对这个问题的态度很明确日常备份一律用-Fc。原因有三一是文件体积小能省不少磁盘二是恢复时可以用sys_restore -j并发加速关键时刻能救命三是支持选择性恢复可以灵活地只捞出某张表。-Fp纯SQL格式也不是一无是处。做跨版本升级、数据库结构对比、或者需要人工检查备份内容里有没有异常对象定义时纯SQL格式最直观。另外如果目标环境连sys_restore都没有那也只能用-Fp加psql来恢复。2.3 常用参数详解与选型理由sys_dump的参数很多但真正经常用到的就那几个我把每个参数背后的选型逻辑讲清楚。-t指定表。注意这里支持通配符比如-t public.*可以匹配public模式下所有表。金仓的表名和模式名都分大小写敏感命令行里传时要注意加引号否则会被转成小写。-n指定模式schema。如果一台实例上跑了多套业务每套业务有自己的schema用-n可以精准地只备份其中一套恢复的时候也不会互相污染。-a和-s分别表示只导出数据、只导出结构。这两个参数在做“只恢复结构”“只灌数据”这种精细化操作用得最多。比如你想在测试环境重建一个空库只建表结构不导业务数据-s就是标准答案。--inserts和--column-inserts是控制数据导出形式的参数。默认情况下sys_dump用的是COPY协议批量导入速度最快但COPY格式的文件对特殊字符处理不友好如果备份文件要在异构数据库之间转换或者要经过中间文本处理建议加上--inserts把数据导成INSERT INTO ... VALUES (...)的形式。代价是文件变大、恢复变慢。-Z压缩级别取值0到9。级别越高文件越小但备份时CPU开销也越高。我实测下来-Z 5是个性价比不错的中间值压缩比和耗时都比较平衡。-E指定编码。多环境迁移时如果源库和目标库的字符集不一致建议显式指定比如-E UTF8避免因为编码差异导致乱码。2.4 一个容易忽略的点一致性快照备份过程中数据库并不是静止的业务可能正在写数据。如果你在下午三点开始备份备份进行到一半某些表的数据已经变了导出来的结果就可能出现“表A的数据是三点零一分快照、表B的数据是三点零二分快照”这种情况跨表数据逻辑上就不是同一个时点这就是一致性问题。金仓的逻辑备份工具默认会尽量拿到一个一致的快照但如果备份过程中有长事务、DDL操作或者导出任务本身没有开启一致性事务仍有风险。解决办法是备份时加上--single-transactionsys_dump -h 127.0.0.1 -p 54321 -U system -Fc --single-transaction -f /backup/testdb.dmp testdb这个参数会把整个备份过程包在单个可重复读事务里保证所有表的数据来自同一个事务快照。代价是备份期间会对数据库的资源占用更高并且备份时长越长事务持有的快照越久可能影响相关表的并发清理。我的建议是重要的业务库和夜间批处理库务必加这个参数白天热库备份时根据负载情况决定。2.5 备份策略和自动化脚本框架备份这事没有自动化就等于没备份。我目前在生产上用的是一个简单但可靠的shell脚本套crontab#!/bin/bash source /etc/profile export KDB_PASSWORDyour_secure_password BACKUP_DIR/backup/kingbase DATE$(date %Y%m%d_%H%M%S) KEEP_DAYS7 sys_dump -h 127.0.0.1 -p 54321 -U system -Fc --single-transaction \ -f ${BACKUP_DIR}/testdb_${DATE}.dmp testdb ${BACKUP_DIR}/backup_${DATE}.log 21 if [ $? -eq 0 ]; then echo $(date %Y-%m-%d %H:%M:%S) backup success ${BACKUP_DIR}/backup.log # 删除7天前的备份 find ${BACKUP_DIR} -name testdb_*.dmp -mtime ${KEEP_DAYS} -exec rm -f {} \; else echo $(date %Y-%m-%d %H:%M:%S) backup FAILED ${BACKUP_DIR}/backup.log exit 1 fi不要小看日志和清理这两步。日志能在第二天早上快速确认备份到底成没成清理则避免磁盘被备份文件堆满。我还有个小习惯每个周的备份文件做一次完整性抽查直接sys_restore --list看一眼归档文件里TOC条目是否完整。3. 逻辑恢复实操从备份文件把数据拉回来3.1 恢复之前先把准备工作做完恢复操作看似是执行一条命令但准备工作做不好恢复过程就是灾难现场。我总结了一个固定的恢复前检查清单确认目标库存在且版本兼容如果备份来自新版本金仓恢复到旧版本可能因为对象定义不兼容而报错。确认目标库的字符集尤其是跨服务器恢复字符集不一致会导致中文乱码或者特殊字符截断。提前创建好需要的角色/用户备份文件里记录的很多对象owner是system或者其他业务账号如果目标环境的账号不存在恢复时通常会因为“role does not exist”而失败。评估磁盘空间恢复过程会同时占用备份文件空间、数据库数据文件空间、WAL日志空间尤其是从-Fp格式恢复时SQL脚本膨胀后的执行体量不容小觑。确认连接信息恢复时连的是目标库sys_restore -d后面跟的库名一定是最终承载数据的库。3.2 plain格式的恢复psql直接灌如果你的备份是纯SQL文本格式那恢复工具就是psql# 先创建目标数据库如果不存在 createdb -h 127.0.0.1 -p 54321 -U system testdb_new # 执行备份文件 psql -h 127.0.0.1 -p 54321 -U system -d testdb_new -f /backup/testdb.sql -e加-e参数可以回显执行的SQL语句方便出问题时定位卡在哪条语句。如果SQL文件很大不建议在交互终端里跑最好用nohup或者脚本放到后台执行并记录日志。这里有个坑如果备份文件里包含了CREATE DATABASE语句比如用-C参数导出的你执行时的目标库就不能是当前库本身需要先连到一个默认库比如金仓维护库再执行否则会互相冲突。3.3 custom/目录格式的恢复sys_restore的正确用法自定义格式最大的价值就是配合sys_restore实现精细化和并发恢复。基础恢复命令# 先建一个空库 createdb -h 127.0.0.1 -p 54321 -U system testdb_restore # 从custom归档恢复开启4个并发任务 sys_restore -h 127.0.0.1 -p 54321 -U system -d testdb_restore -j 4 /backup/testdb.dmp恢复过程中工具会按照依赖顺序自动处理对象创建先建扩展、类型、表再灌数据最后建索引、约束、触发器等依赖前序对象的对象。如果你希望恢复失败时立即停止而不是继续执行并输出一堆错误加--exit-on-error。如果你希望恢复前先清理目标库中已存在的同名对象加-c先DROP再CREATE配合--if-exists避免报错。还有一个容易忽视的参数--no-owner当目标环境的用户和备份时的owner不一致或者你不想让恢复后的对象归属原owner时加上它可以让所有对象归属于当前执行恢复的用户。权限敏感的库恢复时我一般也同时加--no-privileges避免把授权语句也灌进去。3.4 如何只恢复一张表或一个schema这是实际运维里高频到离谱的场景一张表被误删了你不可能为了它把整个库恢复一遍更不可能在正在运行的生产库上覆盖全部对象。这时custom格式的优势就体现出来了。第一步先看归档文件里有哪些条目sys_restore --list /backup/testdb.dmp /tmp/toc_list.txt这个TOC列表会把备份里所有对象条目列出来是一条条带编号的记录。你想恢复哪张表就在列表里找到对应的TABLE DATA条目编号。第二步两种恢复方式任选# 方式一直接按表名恢复只恢复表结构加数据 sys_restore -h 127.0.0.1 -p 54321 -U system -d testdb \ -t public.order_info /backup/testdb.dmp # 方式二基于TOC列表文件只选择部分条目 grep TABLE DATA public order_info /tmp/toc_list.txt /tmp/only_order.txt sys_restore -h 127.0.0.1 -p 54321 -U system -d testdb \ -L /tmp/only_order.txt /backup/testdb.dmp这里要特别提醒按表恢复时如果该表有外键引用其他表或者依赖序列、触发器单独恢复一张表可能只恢复表本身不会自动带出所有关联依赖。所以恢复完成后务必检查外键、序列值、触发器是否完整。数据一致性要求高的场景宁可恢复整个schema然后在目标库删掉不需要的对象。3.5 恢复顺序与依赖关系为什么重要逻辑备份文件里的对象是有依赖关系的先建表后建索引先建父表后建子表先建序列再把序列的默认值挂到列上。sys_dump在生成备份时已经按依赖关系排好了顺序所以正常情况下直接恢复不会乱。但有一种情况会导致依赖问题你手动编辑了TOC列表文件或者备份SQL把对象挑出来单独执行。比如说你先执行了包含数据的部分却没有先建出目标表数据导入显然会失败。再比如你恢复了一张表但它引用的序列没有恢复后续插入数据时主键就会报“序列不存在”。这些坑我都在生产环境里踩过经验是能不动备份文件的内部顺序就尽量不动确实需要精准恢复时优先用-t参数而不是手工裁剪文件。实在是两张关系紧密的表要一起恢复把它们放在同一个-t参数后面用逗号分隔。4. 实战中高频踩坑记录与排查思路4.1 恢复时报权限不足典型报错是permission denied for schema public或者role “xxx” does not exist。原因往往是目标库缺少备份文件里记录的owner角色。排查思路三步走先看备份文件里的owner是谁可以用sys_restore --list挑几条CREATE语句看再查目标环境有没有这个角色没有就先CREATE ROLE创建同名角色。如果不想折腾角色恢复时加--no-owner省去所有权恢复环节。4.2 乱码和字符集问题恢复后一看表里的中文全是问号或者奇怪字符十有八九是字符集没对齐。备份时源库是UTF8恢复时客户端环境变量却是SQL_ASCII或者其他编码执行下来的中文自然就废了。解决方法是备份、传输、恢复三条链路全部保持一致的编码。恢复前用SET client_encoding TO UTF8;或者执行时设置环境变量比如export PGCLIENTENCODINGUTF8 sys_restore -h 127.0.0.1 -p 54321 -U system -d testdb /backup/testdb.dmp另外如果是通过Windows上的工具做中转再传到Linux还要小心文件本身的换行符和BOM头这些细节都能让一个看起来正常的恢复变出乱码。4.3 序列值回退导致主键冲突这是恢复以后最隐蔽的坑。你可以用\d sequence_name查看序列当前值如果序列没有被正确恢复恢复完的表虽然数据都在但新插入数据时主键直接撞上已有记录。为什么会出现这种情况最常见的原因是只恢复了数据-a而没有恢复序列结构或者选择性恢复时漏掉了序列的setval部分。解决方法是恢复完成后做一个快速巡检-- 找到业务表对应的主键序列检查当前值 SELECT last_value, is_called FROM 序列名; -- 有问题的手动设置到最大值之后 SELECT setval(序列名, MAX(id)) FROM 表名;4.4 大备份恢复太慢几十GB的备份恢复要跑几个小时如果没有时间窗口确实让人抓狂。我的加速三板斧恢复期间临时调大maintenance_work_mem这个参数直接影响索引创建和约束建立的速度恢复完再调回去。用sys_restore -j开并发并行恢复数据表、并行建索引能明显缩短整体耗时。但注意并发数别超过服务器CPU核心数否则I/O和CPU互相争抢反而变慢。延迟建索引的备份策略备份时只需要数据结构单独维护或者恢复时用-L列表文件跳过索引部分等数据灌完再统一建索引。这个操作需要你对备份内容非常熟悉谨慎使用。还有一个偏门但有用的技巧恢复时如果允许临时关闭目标表的约束检查通过修改配置文件或在事务中控制灌完数据再统一启用约束能省不少时间。这个操作对一致性要求极高不熟悉金仓行为的话还是别轻易尝试。4.5 恢复到一半失败怎么办恢复不是原子操作除非你用了--single-transaction对恢复来说就是-1参数否则恢复到一半出错时前面成功创建的对象会残留在目标库里。这时候最忌讳的是不清洗直接重跑。残留的表、索引、约束会和备份文件里的CREATE语句冲突报一堆 already exists 错误。正确做法是先DROP SCHEMA public CASCADE; CREATE SCHEMA public;把目标库业务对象清干净或者直接把目标库drop掉重建再重新恢复。如果恢复支持-c --if-exists也可以让工具自动先清理同名对象再建但大库恢复时我仍然建议手动清理一次思路更可控。4.6 常用排查工具箱把上面这些经验整理成一个速查表方便你出问题的时候快速定位现象可能原因解决方法role does not exist目标库缺少owner角色创建同名角色或用--no-ownerpermission denied当前用户权限不足使用超级用户执行或授权schema中文乱码字符集不一致统一UTF8设置PGCLIENTENCODING主键冲突序列值未恢复检查并setval序列already exists残留对象未清理重建库或加-c --if-exists恢复非常慢并发低、内存小、索引重建耗资源调大maintenance_work_mem、用-j并发psql执行到一半退出SQL脚本中有错误用-e回显定位修复后重新恢复备份文件损坏磁盘故障或传输不完整重新备份校验文件大小和TOC列表5. 写在最后我的一些建议最后分享几条这些年做金仓数据库备份恢复工作的真实体会。第一条没有经过恢复验证的备份等于没有备份。我见过太多人每天定时跑备份自以为高枕无忧结果真到恢复的时候发现文件损坏、命令报错、备份内容不全。我现在要求自己至少每季度做一次完整的恢复演练把备份文件恢复到一台测试机上对比关键表行数确认数据可用。第二条逻辑备份和物理备份不是二选一而是互补。逻辑备份胜在灵活、可选择性恢复物理备份胜在速度、全量恢复能力强。单靠任何一种遇到不同的事故场景都会有缺口。第三条恢复时永远给自己留一条后路。恢复之前先把当前生产库再备份一份万一恢复操作出现意外至少还能回到原点。这个习惯救过我太多次了。金仓数据库的逻辑备份与恢复说到底就是“备份要干净、参数要正确、恢复要验证”这三件事。把基础功夫做扎实真到出问题那天你才有底气在五分钟内把数据完好无损地交还给业务。最后再分享一个小技巧如果你想快速确认一份备份文件是否健康不用等恢复结束直接执行sys_restore --list 备份文件.dmp | tail -20看末尾的TOC条目是否完整、有没有警告信息。我每次备份完都会顺手做这个动作几秒钟就能排除掉大半隐性故障。
返回列表