只备份一个 schema,别把整库都搬走

0 阅读6分钟

只备份一个 schema,别把整库都搬走

一个库里塞好几个 schema 是常事:业务表在一个 schema,审计日志在另一个,可能还有给报表、给别的团队用的独立 schema。真要搬东西的时候,往往只想动其中一块——把销售相关的表迁到新库、或者单独打包一份给某个团队,审计日志、别人的业务表都不该跟着走。

这时候整库 sys_dump 就有点大了:不光备了用不上的东西,还可能把不该外传的数据一并带出去。sys_dump 有个 -n,能把备份范围锁死在指定的 schema 上。这篇就用它,把一个 schema 单独备出来,并且一步步确认别的 schema 确实没被顺手捎上。建库删库还是 DBA 的活,用 system 连。

先确认这版 sys_dump 认不认 -n

参数别凭印象写,先翻一眼当前版本的帮助:

sys_dump --help | grep -E "schema|-n|--schema"

确认 sys_dump 支持 schema 过滤

这一行是要找的:

-n, --schema=PATTERN       dump the specified schema(s) only

-n 收一个 PATTERN,只导匹配到的 schema。顺带下面还有个 -N, --exclude-schema=PATTERN,是反过来的——排除某几个 schema、其余都要。这篇用 -n 做「只要这一个」,-N 留着知道有这么回事就行。确认参数在,后面的命令才有依据。

现场:一个库里两个 schema

要看出「只备一个」的效果,库里至少得有两个 schema,一个当主角、一个当参照。这里 sales_schema 放订单和订单明细两张表(还有它们之间的外键),是这次要备的业务;audit_schema 放一张审计日志表,它不是重点,唯一的作用是当对照物——最后用它来证明备份范围没有越界。

两个 schema 建好、灌完数据后,查一下现状:

select table_schema, table_name
from information_schema.tables
where table_schema in ('sales_schema', 'audit_schema')
order by table_schema, table_name;
​
select 'sales_order' as item, count(*) from sales_schema.t_order
union all
select 'sales_item' as item, count(*) from sales_schema.t_order_item
union all
select 'audit_log' as item, count(*) from audit_schema.t_audit_log;

源库里准备两个 schema

audit_schema.t_audit_logsales_schema.t_ordersales_schema.t_order_item 三张表都在,行数分别是审计日志 2 行、订单 3 行、明细 3 行。两个 schema 都有真实内容——接下来只备 sales_schemaaudit_schema 就该原地不动。

(顺一句:information_schema.tables 是标准写法,KES 里也可以用 sys_tables 查,两条查出来一样,看你顺手用哪个。)

备份时用 -n 锁定 sales_schema

关键就一条命令,-n sales_schema 把范围框住,格式还是上一篇的 custom:

sys_dump -h 127.0.0.1 -p 54321 -U system \
  -F c \
  -n sales_schema \
  -f /acowbo/kingbase/backups/schema_20260630/sales_schema.dump \
  schema_src_db
​
ls -lh /acowbo/kingbase/backups/schema_20260630

只备份 sales_schema

备出来一个 3.9K 的 sales_schema.dump。命令里有两点容易看漏:-n sales_schema 是范围控制的核心,-n 后面跟的是 PATTERN,写精确名字就是只要这一个,也能用 -n 'sales*' 这种通配一次匹配多个;命令最末尾那个 schema_src_db 是源库名,别把它跟 -n 的值搞混。

别急着还原,先看归档清单里有什么

上一篇讲过,custom 备份能先用 sys_restore -l 把归档目录列出来,恢复前先验一遍范围对不对。这次就靠它来抓「有没有捎带别的 schema」:

sys_restore -l /acowbo/kingbase/backups/schema_20260630/sales_schema.dump \
  > /acowbo/kingbase/backups/schema_20260630/sales_schema.list
​
grep "sales_schema" /acowbo/kingbase/backups/schema_20260630/sales_schema.list
grep "audit_schema" /acowbo/kingbase/backups/schema_20260630/sales_schema.list

归档清单只包含目标 schema

grep sales_schema 抓出来一串:schema 本身、两张表、两段表数据、两个主键约束、还有明细表指向订单表的外键——sales_schema 里该有的全在。而 grep audit_schema 这条,一行输出都没有。

这个「没输出」不是命令出错,正是这一步要的结果:归档里压根没有 audit_schema 的影子。恢复动作还没做,就已经能确定这份备份的范围没有超出 sales_schema

还原到临时库

范围确认过了,还原到一个临时库看看,不去碰源库:

sys_restore -h 127.0.0.1 -p 54321 -U system \
  -d schema_restore_db \
  -v \
  /acowbo/kingbase/backups/schema_20260630/sales_schema.dump

还原 schema 备份到临时库

-v 把过程打出来:建 sales_schema、建 t_ordert_order_item、灌数据各 3 行、建主键、建外键。从头到尾只跟 sales_schema 打交道,没有一句提到 audit_schema——归档里没有的东西,还原自然也变不出来。

验收:临时库里只有 sales_schema

最后到临时库里正面查一遍,把范围坐实:

select table_schema, table_name
from information_schema.tables
where table_schema in ('sales_schema', 'audit_schema')
order by table_schema, table_name;
​
select count(*) as order_count from sales_schema.t_order;
select count(*) as item_count from sales_schema.t_order_item;
​
select count(*) as audit_table_count
from information_schema.tables
where table_schema = 'audit_schema';

临时库验证只恢复目标 schema

临时库里查两个 schema,只列出 sales_schemat_ordert_order_item两张表;订单 3 行、明细 3 行,跟源库对得上。最后专门数一下 audit_schema 的表数量,是 0——一张都没进来。

到这儿,三道关是一致的:备份命令用 -n 框了范围,归档清单里 grep audit_schema 没输出,还原后的库里 audit_schema 表数为零。范围控制不是靠「命令跑成功了」这一句话,而是从备份包到恢复结果都对得上。

什么时候用,什么时候别硬套

-n 适合的场景很明确:库里分了多个 schema,这次只想动其中一块——迁一块业务到新库、单独给某个团队一份数据、或者只想验证某个 schema 的备份能不能用。范围小,备份快、文件小,也不会把不相干的数据裹出去。

但它只是「范围更小的一种备份」,不是所有场景的默认选择。整库有整库的用处,真要迁移一个完整的库,老老实实整库备更省心,没必要拆成一个个 schema。

还有一个坑得记在心里:-n 只管一个库内部的 schema,也只保证把这个 schema 的对象打包进去。如果 sales_schema 里的对象引用了别的 schema——比如外键指向 audit_schema 的表、或者视图 join 了别处的表——单独备 sales_schema 就可能把这些跨 schema 的依赖漏在外面,还原到干净的库时会因为找不到被引用的对象而报错。这篇的 sales_schema 内部自洽(外键都在自己 schema 内),所以干净;真实业务里备单个 schema 前,先摸清楚它有没有伸到别的 schema 去的手。

下一篇范围再缩一档:不是一个 schema,而是只把一张表从备份里单独捞回来。