
前阵子处理了一个挺典型的故障Windows服务器上的KingbaseES业务库某天被一条错误的update把主表数据整成了缺数据的状态。业务方急库又不能随便停。好在数据库此前按计划跑过sys_dump的库级逻辑备份我拿最近的dmp文件把这张表的数据单独导出来补回去十几分钟就收工了。作为在Windows上维护金仓数据库的DBA这应该算是最常用的一种保命手段。本文是Kingbase备份恢复实战系列的第二篇不再讲选型大道理直接落到sys_dump这个工具在Windows环境下的完整操作命令长什么样、参数怎么组合、恢复时走哪条路、哪些坑必须绕开。文中所有操作都以V008R003C002B0160版本为基础测试过不同小版本大同小异命令本身兼容性很好。1. Windows下做备份为什么先考虑sys_dump而不是直接拷数据文件1.1 逻辑备份与物理备份的分工很多刚接触金仓的朋友第一反应是备份数据库把整个数据目录拷走不就行了在Windows上确实有人这么干但这么干的前提是库要停或者你愿意承担拷贝过程中数据文件不一致导致库起不来的风险。金仓的数据文件在数据库运行期间处于持续写入状态直接拷贝文件等于在写一半的时候拍照拍出来的照片可能是坏的。除非用底层卷影复制、磁盘快照这类手段否则不推荐在生产环境这么玩。sys_dump做的事情完全不一样。它连上数据库在一个一致性快照里读取所有对象定义和数据然后生成一份逻辑上的备份。这份备份不是数据文件的副本而是“重建数据库所需的指令合集”。打个比方物理备份是把整个房子连同家具整体搬走逻辑备份是给每个房间列一份物品清单之后按清单重新把房子搭起来。Windows环境下的中小型业务库绝大部分场景用sys_dump就够了。1.2 什么场景适合什么场景不适合从我接触过的项目经验来看下面这些场景很适合sys_dump数据库体积在几十GB以内逻辑导出耗时可控备份文件也方便离线存放。需要做跨版本迁移比如从V8的一个小版本迁到另一个小版本或者换机器换实例。需要恢复单个表、单个schema而不是整库恢复。需要定期把生产库导出一份给测试环境用。不适合的场景也很明确库里几百GB甚至TB级导出动辄几个小时恢复时又要回放大量SQL这时候逻辑备份的效率就撑不住了。增量备份、持续归档、秒级恢复这些需求逻辑备份也做不到得老老实实上物理备份加归档日志的方案。所以选哪条路不是看哪个工具更“高级”而是看你的数据量和恢复时间要求。1.3 导出产物到底是什么备份格式怎么选sys_dump支持三种输出格式用参数-F指定分别是格式参数产物恢复方式典型场景纯文本SQL-Fp单个.sql文件含DDL和COPY数据ksql执行跨版本迁移、手工审阅自定义归档-Fc单个.dmp文件压缩存储sys_restore日常备份、选择性恢复目录归档-Fd一个目录内部多个文件sys_restore大型库备份、并行恢复我日常最推荐-Fc。它体积小支持sys_restore按表恢复还支持恢复到目标库时灵活指定参数。纯文本SQL格式虽然能直接用记事本打开看内容但恢复时必须整份回放想捞一张表出来比较费劲。目录格式在Windows上也不是不能用但日常维护多一个目录管理起来麻烦除非单库特别大否则-Fc足够应对大多数情况。2. 动手前的准备找到sys_dump、配好连接、确认权限2.1 找到bin目录先让命令能直接用Windows下最容易被卡住的第一步是根本找不到sys_dump这个命令。金仓安装后的bin目录位置因安装方式而异常见的位置有C:\Program Files\Kingbase\ES\V8\binC:\Program Files\Kingbase\ES\V8\KESRealWeb\bin自定义安装目录下的bin文件夹不确定的话在开始菜单里找到“命令提示符”执行where sys_dump如果没输出再去安装目录里搜一下sys_dump.exe。找到bin目录后建议不要改系统全局PATH而是在命令行窗口里临时设置特别是你后面要写批处理脚本时这种做法更干净set DBBINC:\Program Files\Kingbase\ES\V8\KESRealWeb\bin set PATH%DBBIN%;%PATH%注意路径外面套了双引号。Windows的Program Files中间有空格不加引号cmd会把路径拆成好几段后面命令怎么执行都是错的。2.2 连接验证端口、数据库、用户金仓默认实例端口是54321安装时通常初始化一个名为test的数据库超级用户是system。不同项目可能改过但验证命令的思路一样。先用sys_dump自带的版本命令确认工具可用sys_dump --version能输出版本号说明命令本身没问题。然后验证能否连上目标库ksql -h 127.0.0.1 -p 54321 -U system -d test -c select version();执行后输入密码能看到数据库版本信息就说明连接通了。如果连不上按这个顺序排查服务是否启动net start | findstr /i kingbase或者直接在服务管理器看金仓服务状态。端口是否对登录数据库后在ksql里执行show port;。防火墙是否放行54321端口本机执行备份通常不受影响远程执行备份必须放行。2.3 权限怎么给普通用户和超级用户的差别sys_dump导出的是它连接用户能看到的所有对象。如果你用一个普通业务账号去导全库经常会出现一堆WARNING提示某些对象没有权限被跳过导出来的备份不完整恢复时才发现少了表或者少了函数。我踩过这个坑某次用应用账号导全库结果公共schema下几张表没导进去恢复完测试环境一跑就缺对象。所以做全库备份时强烈建议用超级用户system或者专门的sys_dump账号。金仓的权限模型继承自PostgreSQL超级用户能读取所有对象定义和数据。如果公司安全策略不允许用超级用户做日常备份那就给备份账号单独授所有schema的USAGE和SELECT权限至少保证导出的范围可控、可预期。3. 第一条全库备份命令参数逐个吃透3.1 标准写法环境准备好了直接看完整命令sys_dump -h 127.0.0.1 -p 54321 -U system -d test -Fc -f D:\kingbase_backup\test_20250104.dmp逐项拆开看-h 127.0.0.1数据库主机地址本机备份写127.0.0.1即可。-p 54321端口跟数据库实际端口保持一致。-U system连接用户全库导出用超级用户或专用备份账号。-d test要导出的库名。-Fc采用自定义归档格式。-f D:\kingbase_backup\test_20250104.dmp输出文件路径。执行后如果一切正常屏幕只会输出极少信息命令行提示符直接回来。在Windows的cmd里可以顺手看一眼错误码echo %errorlevel%输出0说明导出成功非0说明中途出了问题。这个习惯很值钱后面写定时任务脚本时基本就是靠它判断备份成败。3.2 常用参数速查表sys_dump的参数很多日常真正用到的其实就下面这些参数含义示例-n指定schema-n public只导public-t指定表可多次-t public.orders -t public.users-T排除指定表-T public.big_log--schema-only只导结构不含数据配合版本发布使用--data-only只导数据不含结构迁移数据时配合目标库已建好的表--no-owner不导出OWNER语句跨用户恢复时避免权限报错--no-privileges不导出权限授权语句恢复时不想复制原库授权--clean生成的脚本里包含DROP语句纯文本格式恢复前先清理旧对象--if-exists配合--cleanDROP前加IF EXISTS避免对象不存在时报错这些参数可以组合使用。比如只导结构加清理语句sys_dump -h 127.0.0.1 -p 54321 -U system -d test --schema-only --clean --if-exists -f D:\backup\test_schema.sql生成的.sql文件里每个CREATE TABLE之前都会带一句DROP TABLE IF EXISTS恢复到测试库时不用手工清表直接执行脚本就行。3.3 怎么判断备份真的成功了很多人导完看一眼有文件就认为完事了其实文件存在只能说明有输出不代表内容完整。我习惯上做两步验证先看文件体积是否合理。一个几十MB的库导出来只有几KB那肯定有问题八成是连接用户权限不够导出过程中跳过了一堆对象。再看备份内容。纯文本SQL文件可以直接用记事本打开检查开头有没有完整的CREATE TABLE、COPY等语句。自定义格式-Fc就要用sys_restore来列表览sys_restore --list D:\kingbase_backup\test_20250104.dmp输出会是一个长清单包含表、序列、函数、索引等条目。能正常列出说明这个备份文件结构完好可以放心归档。4. 按业务场景组合参数结构、单表、排除表与定时备份4.1 只要结构、只要数据日常运维里“只要一半”的场景特别多。比如给测试环境同步表结构不需要生产数据或者目标库表已经建好只缺数据。这时候用--schema-only和--data-only最合适。只导结构sys_dump -h 127.0.0.1 -p 54321 -U system -d test --schema-only -f D:\backup\test_schema.sql只导数据sys_dump -h 127.0.0.1 -p 54321 -U system -d test --data-only -Fc -f D:\backup\test_data.dmp这里有个细节要注意只导数据时数据的插入顺序可能和外键约束冲突。比如父表数据还没导进去子表的INSERT就被外键挡了。遇到这种情况要么分表处理要么恢复时用--disable-triggers临时关闭触发器。sys_restore有一个同名的--disable-triggers参数可以在数据导入期间临时禁用触发器导入完成后再恢复非常实用。4.2 按schema和表选择性导出如果库里只有一小部分业务需要单独备份没必要每次都全库跑。金仓支持用-n按schema导出用-t按表导出用-T排除不想导的表sys_dump -h 127.0.0.1 -p 54321 -U system -d test -n public -Fc -f D:\backup\public.dmpsys_dump -h 127.0.0.1 -p 54321 -U system -d test -t public.orders -t public.order_items -Fc -f D:\backup\orders.dmpsys_dump -h 127.0.0.1 -p 54321 -U system -d test -T public.big_log -T public.temp_2024 -Fc -f D:\backup\main.dmp第三个例子很常见业务大表、临时表不需要进入日常备份用-T排除后备份文件体积能小一大截恢复时间也跟着缩短。如果你在Windows下用命令行时表名带了schema前缀注意别漏掉点号public.orders不能写成publicorders这种低级错误我见过不止一次。4.3 Windows批处理脚本自动备份定时备份是Windows运维绕不开的环节。sys_dump本身不带调度功能需要借助Windows任务计划程序。这里给一份我实际在用的批处理脚本改改路径就能用echo off set DBBINC:\Program Files\Kingbase\ES\V8\KESRealWeb\bin set BAKDIRD:\kingbase_backup if not exist %BAKDIR% mkdir %BAKDIR% for /f %%i in (powershell -Command Get-Date -Format yyyyMMdd) do set DT%%i %DBBIN%\sys_dump.exe -h 127.0.0.1 -p 54321 -U system -d test -Fc -f %BAKDIR%\test_%DT%.dmp if %errorlevel%0 ( echo %date% %time% backup OK test_%DT%.dmp %BAKDIR%\backup.log ) else ( echo %date% %time% backup FAILED test_%DT%.dmp %BAKDIR%\backup.log )注意我拿到期格式用的是PowerShell的Get-Date -Format yyyyMMdd而不是%date:~0,4%这种切片写法。原因是Windows不同系统、不同区域设置下%date%输出格式不一样有的带斜杠有的带星期几切片一错文件名就变成test_202/05/0.dmp这种废品。用PowerShell统一输出yyyymmdd格式最稳。然后把脚本注册到任务计划程序schtasks /Create /TN KingbaseAutoBackup /TR D:\kingbase_backup\daily_backup.bat /SC DAILY /ST 02:00 /RU SYSTEM /F/SC DAILY /ST 02:00表示每天凌晨2点执行/RU SYSTEM用系统账户运行避免普通账户密码变化导致任务失效。如果有清理需求再加一条保留7天备份的命令forfiles /p D:\kingbase_backup /s /m *.dmp /d -7 /c cmd /c del path4.4 备份窗口的选择sys_dump在数据库运行期间就能执行不会阻塞业务读写这是它的优势。但它毕竟要占用CPU和磁盘IO全库导出时内存和IO都会有明显波动。我建过一套几十GB的库备份跑到一半刚好赶上业务高峰整个实例的查询响应明显变慢。所以备份时间尽量挑凌晨低峰期至少避开整点批处理任务集中的时段。还有一个很重要的点备份过程中不要有DDL变更。虽然sys_dump有快照保证数据一致性但DDL和备份并发时偶尔会报“invalid snapshot”一类的错误重新导一次又好了但你要是在凌晨等着备份结果睡觉这种意外真的很折腾人。5. 恢复时走哪条路ksql、sys_restore与恢复前检查5.1 纯文本SQL脚本用ksql执行先分清两种恢复方式。纯文本SQL格式的备份文件本质就是一个带CREATE TABLE、COPY、CREATE INDEX等语句的脚本恢复工具是ksql。命令很直观ksql -h 127.0.0.1 -p 54321 -U system -d test -f D:\kingbase_backup\test_20250104.sql有时候你已经进到ksql交互界面里了不想退出再执行外部命令那就用内置的\i命令注意Windows路径最好写成正斜杠\i D:/kingbase_backup/test_20250104.sql纯文本恢复有个坑如果目标库里已经存在同名表执行到CREATE TABLE时会报错但脚本不会停下来后面的语句继续执行。结果就是一半新一半旧你很难判断最终数据对不对。所以用纯文本脚本恢复前要么先drop旧库重建要么确认目标库是干净的。5.2 自定义格式用sys_restore并且可以只恢复某张表-Fc自定义格式必须用sys_restore恢复。最标准的全库恢复命令是把旧对象清掉再重建sys_restore -h 127.0.0.1 -p 54321 -U system -d test --clean D:\kingbase_backup\test_20250104.dmp--clean参数会在恢复过程中先执行DROP TABLE/SEQUENCE/VIEW等语句把目标库里的旧对象清掉再重新创建并导入数据相当于给目标库做了一次“覆盖式恢复”。注意执行这个命令的人必须有目标库的DROP权限普通业务账号一般不够。如果目标库还不存在可以加-C参数让sys_restore自动建库sys_restore -h 127.0.0.1 -p 54321 -U system -d test2 -C D:\kingbase_backup\test_20250104.dmp这条命令会先创建test2这个数据库再把备份恢复到里面非常适合“从备份里拉一个临时库出来看看”的场景。sys_restore还支持按对象选择性恢复这是-Fc格式相比纯文本最大的优势。比如我只想从备份里捞回orders这一张表sys_restore -h 127.0.0.1 -p 54321 -U system -d test --clean -t public.orders D:\kingbase_backup\test_20250104.dmp开头提到的那个故障我实际用的就是这条命令加-t参数只恢复了被误操作的那张表不影响其他业务。如果你用目录格式-Fd做了备份恢复命令的最后一个参数要改成目录路径其余参数一样。5.3 恢复前我必做的四项检查恢复动作本身很快但恢复前的检查不能省。我习惯按下面这个清单过一遍目标库版本和备份来源版本是否兼容跨大版本恢复优先用纯文本SQL格式。目标库磁盘空间是否足够数据量翻倍的情况不是没发生过。目标库里已有对象是否有同名冲突特别是用--clean恢复时确认clean不误删业务上不能删的对象。先在一个空库或测试库演练一次恢复流程确认备份文件可用再动生产库。其中第4条最重要。备份文件如果坏了早发现总比生产恢复时才发现好。所以我的习惯是每一次全量备份做完顺手在备机上做一次恢复演练耗时半小时但能保证每一个备份文件都是真的可用的。6. Windows环境特有的坑乱码、空格、定时任务失败与版本兼容6.1 控制台编码与库内编码不一致导致的乱码Windows中文系统下cmd默认代码页是936GBK而金仓数据库初始化时常用的编码是UTF8。两边编码不一致最直接的表现是ksql里查询中文正常但执行备份时日志里中文乱码导出的SQL文件里中文要是再乱恢复就会出现问号。解决路径分两步。先让控制台切到UTF8代码页chcp 65001再通过环境变量指定客户端编码让sys_dump和ksql发出的数据都按UTF8走set PGCLIENTENCODINGUTF8这两条命令要在执行备份或恢复的同一个命令行窗口里先跑。如果只是想临时改ksql交互界面的编码不进命令行直接执行\encoding UTF8也行。写入批处理脚本时把这两行放在脚本开头可以避免管理员忘记了而手动执行。6.2 路径带空格和引号问题Windows安装软件时默认路径基本都带空格Program Files这个目录名是重灾区。如果你照抄命令时不加引号cmd会把路径按空格拆开出现C:\Program 不是内部或外部命令也不是可运行的程序或批处理文件。看到这个报错第一反应不是查命令而是要检查路径引号。正确写法是把整个路径用双引号包起来C:\Program Files\Kingbase\ES\V8\KESRealWeb\bin\sys_dump.exe -h 127.0.0.1 -p 54321 -U system -d test -Fc -f D:\backup\test.dmp在批处理脚本里如果引号嵌套多了容易乱我的做法是把长路径赋值给变量变量名不带空格后面引用变量外面再套引号。这样即使路径变了只需要改一处变量赋值。6.3 计划任务看起来跑了但备份没产出定时任务最大的坑是任务计划程序显示“已运行”但备份文件根本没生成。我遇到过的原因大概有几种批处理脚本里的相对路径找不到sys_dump.exe因为任务计划的工作目录跟手工执行时不一样。用SYSTEM账户运行时SYSTEM账户可能没有访问某个网络共享目录的权限。脚本执行过程中弹了个交互提示框比如密码输入任务一直卡住直到超时。排查时不要光看任务状态先看脚本里有没有写日志。我在前面的脚本里把backup OK或backup FAILED都追加到了backup.log这样任务一跑完就能看到结果。如果日志显示FAILED再手工双击脚本排除脚本本身的问题。如果手工能成功但系统跑不成功多半是账户权限问题优先检查SYSTEM账户对备份目录是否有写权限。6.4 版本号差异带来的兼容性问题金仓的版本号长这样V008R003C002B0160拆开看是V8主版本、R3大版本、C2小版本、B0160构建号。日常备份恢复时同主版本下跨小版本基本没问题。如果机器上装了多个金仓版本记得用目标数据库对应安装目录下的sys_dump和ksql不要从PATH里随便找一个。我自己就吃过亏机器上装了一套旧版客户端备份新库时导到一半报版本不兼容后来统一改用数据库实例自带的bin目录工具再没出过问题。如果遇到跨大版本迁移比如从V8迁移到更新的大版本我建议用-Fp纯文本SQL格式导出再用ksql在新库执行。纯文本SQL对版本差异的容忍度最高虽然执行过程中可能出现个别语法不兼容的报错但至少能逐条看到错误逐个处理总比自定义格式整个恢复失败要好排查。最后分享一个我自己的习惯每次备份完成后在备份日志里记录备份文件的文件名和大小恢复时用sys_restore --list核对一下里面的对象清单。有了这份记录备份文件真的出问题时你能很快判断是哪个环节出了偏差而不是对着一个孤零零的dmp文件干着急。这套防呆流程帮我省下来的时间说实话比备份本身还多。