前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 3|回复: 0

[开发应用] Sybase ASE 备份恢复实战:从 dump/load 到时间点恢复

[复制链接]

[开发应用] Sybase ASE 备份恢复实战:从 dump/load 到时间点恢复

[复制链接]
dbaai

主题

0

回帖

326

积分

DBAAI

积分
326
3 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
上周五晚上六点,开发同事在测试库上跑错了一个 UPDATE,where 条件少写了半截,二十多万行订单状态被刷成同一个值。DBA 组的第一反应是恢复,结果翻配置一看:这个库每周日只做一次 dump database,事务日志按 last-chance threshold 自动 dump 之后就被截断了。也就是说,最多要丢六天的数据,谁也兜不住这个责任。最后是靠开发从应用日志里人工拼出被改的行,加班到凌晨两点才补回来。这篇文章就把 Sybase ASE 的备份恢复体系从头捋一遍,重点讲清楚 dump/load 怎么搭、时间点恢复怎么做,以及为什么"每周一个全量"在出事那天救不了你。

一、具体的问题

很多 ASE 环境的备份策略常年停留在两个状态:要么只有一个周日全量 dump database,中间的日志全被 truncate 掉了;要么知道要 dump transaction,但从来没实际演练过 load,真出事的时候才发现日志备份链断了、设备不全、load 不上去。具体表现有三类:


  • 全量备份之间的事务全部丢失。dump database 拿到的只是一个静态的物理快照,周日备份、周五出事,周一到周四的数据没有第二份。
  • 日志 dump 链不连续。中间某次手工执行了 truncate_only 或者 no_log(救 1105 的时候),链子就断了,后面的日志备份全部作废,但从断点之后到出事那一刻的数据也全丢。
  • load 的顺序和选项搞错。load database 之后忘了 load transaction,或者不知道 until "time" 这个用法,恢复出来的库要么停在很早的时点,要么干脆 online 不起来。


二、核心原理

ASE 的备份恢复是物理级的,理解三条主线就够:

第一,dump database 是整库数据页的物理拷贝,由 Backup Server(sybmultbuf)完成,不占 Adaptive Server 的主引擎资源。它记录的是备份那一刻的落库状态,恢复时 load database 会把库置于 offline 状态等待日志续放。

第二,dump transaction 是事务日志的增量备份。只要日志截断点(truncate point)在 dump 时被推进,两条相邻日志备份之间就是无缝的。时间点恢复的本质是:load 全量,然后按顺序 load 每一份事务日志,最后一份可以指定 until "time" 精确到秒。这条链子的前提是中间没有被 truncate 打断——这正是上一篇讲 1105 应急时强调"no_log 之后必须立刻 dump database"的原因:它是重新起链。

第三,last-chance threshold 自动 dump tran 是日志段的保险丝,但它是"保日志段不爆"的机制,不是备份策略本身。阈值 dump 出来的日志确实进了备份链,但如果没人核对 dump 设备和保留期,链子照样有洞。备份策略要用 cron/作业调度按固定周期主动 dump transaction,阈值 dump 只做兜底。

三、实例参考(动手步骤)

以下场景假设:订单库 orderdb,数据 80GB,日志 20GB,目标是出事后能恢复到出事前一分钟。

步骤 0:确认现状基线
  1. -- 确认日志没有按检查点自动截断(截断了就做不了时间点恢复)
  2. sp_helpdb orderdb
  3. -- 看 status 列,绝不能有 "truncate log on chkpt"
  4. -- 确认 Backup Server 在跑
  5. sp_who   -- 应能看到 BACKUP SERVER 相关进程
  6. -- 或者直接在 shell 看 backupserver 进程
  7. -- 看现有 dump 设备
  8. sp_helpdevice
复制代码

步骤 1:规划 dump 设备与周期

dump 到文件系统比裸设备好管理,建议每库两个条带并行提速:
  1. mkdir -p /backup/orderdb
复制代码
  1. -- 全量:每周日 01:00,两路条带 + 压缩
  2. dump database orderdb
  3.   to "/backup/orderdb/full_1.dat"
  4.   stripe on "/backup/orderdb/full_2.dat"
  5.   with compression = 2, init
  6. go
  7. -- 日志:每 15 分钟一次,工作日高峰可加密到 5 分钟
  8. dump transaction orderdb
  9.   to "/backup/orderdb/tran_20261015_1200.dat"
  10.   with compression = 2, init
  11. go
复制代码

用 crontab 或者 ASE 的 job scheduler 驱动,文件名必须带时间戳,脚本里先判断空间再 dump。

步骤 2:验证备份可恢复(备份没验证过等于没备份)
  1. -- 检查 dump 文件内容与日志链
  2. load database orderdb
  3.   from "/backup/orderdb/full_1.dat"
  4.   with listonly, header
  5. go
复制代码

listonly 能列出这份全量对应的日志链起点,tran 备份的 header 能看出它续在哪一份之后。每周抽一份全量 + 当天日志,load 到一台备用机或临时 dataserver 上,跑一遍 dbcc checkalloc / checkdb,确认数据可读。

步骤 3:时间点恢复演练(重点)

假设 12:47 发生误 UPDATE,12:45 有最后一份正常日志备份:
  1. -- 1. load 全量(周日那份),库进入 offline loading 状态
  2. load database orderdb
  3.   from "/backup/orderdb/full_1.dat"
  4.   with compression = 2
  5. go
  6. -- 2. 按时间顺序依次 load 所有日志备份,普通份不带 until
  7. load transaction orderdb
  8.   from "/backup/orderdb/tran_20261015_1030.dat"
  9.   with compression = 2
  10. go
  11. -- 3. 最后一份用 until 停在误操作前一分钟
  12. load transaction orderdb
  13.   from "/backup/orderdb/tran_20261015_1230.dat"
  14.   with compression = 2,
  15.   until "Oct 15 2026 12:46:00:000PM"
  16. go
  17. -- 4. 联机
  18. online database orderdb
  19. go
复制代码

load transaction 是可重入的:如果 until 的时间设早了想再往后放,直接重新执行 load transaction 即可,不需要从全量重来。恢复完成后第一件事是立刻再做一次 dump database,重新起链。

步骤 4:改错恢复的止损路径

如果只是单表被误改且表不大,更快的路子是"并行恢复出副本库、再单表搬回":把 orderdb 的 dump load 到一个临时库名(load database 支持 with file = 指定逻辑页设备时可换库名的场景,更通用的做法是建一个空库名 orderdb_rec,直接 load 进去),online 之后用 bcp / insert-select 把误改表导回主库,全程主库不停服。

四、实操检查清单


  • sp_helpdb 确认目标库 status 不含 truncate log on chkpt,含了立即关掉
  • Backup Server 进程存活,dump 前先确认而不是事后发现
  • 全量每周至少一次,事务日志 15~30 分钟一份,文件名带时间戳且脚本判断磁盘空间
  • 日志链完整性:每周核对最近一次 dump transaction 的 header,确认它续在上一次之后
  • 每周一次"全量 + 日志"真机恢复演练,dbcc checkalloc 通过才算数
  • master 库也要备份(dump database master),并保留 disk init 记录,防止 master 损坏时设备信息无处可查
  • dump 目录与数据库数据目录不同盘、不同主机(有条件走 NFS 到备份机)
  • 保留期与空间清理脚本绑定,防止 /backup 写满导致当晚 dump 全部失败
  • 恢复预案成文:谁执行、load 顺序、until 语法、online 命令,写清到可以直接照抄


几个容易踩的坑


  • with truncate_only / no_log 之后再做的时间点恢复,只能恢复到 no_log 那一刻,之后的日志全丢——救急之后立刻 dump database 重起链子,这篇和 1105 那篇是同一枚硬币的两面。
  • dump transaction with no_truncate 是数据设备坏了但日志设备还活着时的救命选项,它绕过截断点把日志整个备走,别和普通 dump tran 混用。
  • load database 之后如果忘了后续 load transaction 就直接 online,未恢复的日志区间直接作废,库就停在 load 全量的那一刻。
  • until 时间用错了时区或格式(ASE 用服务器本地时间,格式要写成 "Oct 15 2026 12:46:00:000PM" 这种),宁可按日志文件的时间戳倒推,也别手敲猜。
  • 压缩的 dump(with compression)load 时同样要带 compression 参数,两边设备字符集(-J)也要一致,否则 load 报格式错误。
  • 备份脚本成功不等于备份有效:磁盘写满写了一半、NFS 掉线后 dump 报错但 cron 邮件没人看,这类"假成功"只有真恢复演练能兜住。


治理前后对比

orderdb 按 80GB 数据 + 15 分钟日志周期改造后,同一次误 UPDATE 场景的恢复效果:

指标改造前(仅周日全量)改造后(全量+15min日志)
最大数据丢失窗口6 天≤15 分钟
恢复到指定时点能力无精确到秒(until)
全量恢复耗时(80GB)约 55 分钟约 40 分钟(双条带)
日志追加恢复(15 份)不可用约 8 分钟
每周恢复演练0 次1 次,dbcc 通过
误改止损路径人工拼日志副本库单表搬回,主库不停服


备份体系的价值不在备份那天,而在出事那天。ASE 这套 dump/load 机制本身很皮实,坑都在流程里:链子断没断、备份验证没验证、until 语法练没练过。把清单跑一遍,比出事后再翻文档强得多。
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-10-15 08:56 , Processed in 0.022199 second(s), 9 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表