【DB2 数据库】12 备份恢复实战:离线全备、持续前滚与最小停机接管
文章目录62 节
一、这篇文章要验证什么
这次实验不是只执行一次 BACKUP 和 RESTORE,而是围绕两类核心恢复目标,记录四个实测阶段,并补充常见备份恢复场景和参数边界:
- 使用离线全备恢复出备份时刻的一致性快照。
- 把全备恢复到另一台服务器,长期保持
ROLLFORWARD PENDING,多轮应用主库最新归档日志,但不立即执行STOP。 - 切换前先让备库追到接近主库的位置,只在最终停写后传送一小段尾日志。
- 在备库执行
AND STOP,验证最终数据、RPO、RTO、新日志链以及接管后备份。
第二种方式本质上是一套基于备份与归档日志传送的暖备方案。它不是 DB2 HADR,也不是双活;备库在接管前不能提供普通 SQL 访问,但可以持续缩短与主库之间的日志差距。
实验过程中还保留了真实遇到的错误,包括路径大小写、零字节备份、DB2 9.7 参数顺序、前滚状态误读和接管后的归档状态检查。
二、脱敏后的实验环境
本文中的主机名、地址、数据库名和路径均已替换为实验示例。正式操作时必须按实际环境修改。
| 项目 | 主库 | 备库 |
|---|---|---|
| 主机名 | db-primary | db-standby |
| 示例地址 | 192.0.2.10 | 192.0.2.20 |
| 操作系统 | SLES 12 SP5 | SLES 12 SP5 |
| DB2 | 9.7 FP6 64 位 | 9.7 FP6 64 位 |
| 实例用户 | db2inst1 | db2inst1 |
| 数据库 | LABDB | 由备份恢复生成 |
| 数据目录 | /db2data | /db2data |
| 备份目录 | /db2backup | /db2backup |
本文命令默认以 db2inst1 用户执行。示例数据库使用 GBK、CN Territory、4 KB 页面,属于单分区数据库。
flowchart LR
P["主库 db-primary<br/>正常提供读写"]
B["完整备份<br/>standby_seed"]
A["连续归档日志<br/>S0000000.LOG ..."]
S["备库 db-standby<br/>ROLLFORWARD PENDING"]
C["切换前预同步<br/>不执行 STOP"]
N["最终尾日志 + AND STOP<br/>备库成为新主库"]
F["接管后在线全备<br/>建立新恢复基线"]
P -->|"离线全备"| B
P -->|"持续归档"| A
B -->|"RESTORE"| S
A -->|"多轮 ROLLFORWARD"| S
S --> C
C --> N
N --> F三、实验前必须确认的边界
1. 本实验不预先创建同名数据库
本实验中的备库 LABDB 由主库备份恢复生成,不提前创建同名空库。恢复前执行:
db2 list db directoryDB2 支持通过 INTO 恢复成其他名称,也支持在明确授权后用 REPLACE EXISTING 覆盖已有目标,但后者具有破坏性。如果备库已经存在同名数据库,必须先确认它是否可以删除或覆盖,不能直接处理生产或测试数据。
2. 克隆服务器不能只修改主机名和 IP
如果备机由主机克隆得到,还要检查:
db2set -all
cat ~/sqllib/db2nodes.cfg单分区实例的 DB2SYSTEM 和 db2nodes.cfg 应指向备机自身,而不是克隆源主机。
克隆虚拟机还可能继承源机的 SSH host key。应在备机重新生成主机密钥,并在客户端核对新指纹,不能通过关闭 host key 校验绕过安全检查。
3. 数据、日志和备份路径必须分开确认
本实验使用:
/db2data/onlinelog/LABDB
/db2data/mirlog/LABDB
/db2backup/LABDB/archive
/db2backup/LABDB/offline
/db2backup/LABDB/standby_seed
/db2backup/LABDB/rollforward_logs这些路径不是 DB2 固定路径。正式执行前要确认挂载点、容量、所有者、权限和备库上的目标目录。
四、先做选型:备份、恢复与前滚如何组合
1. 先区分四个容易混淆的概念
本文统一使用 DB2 的准确术语:
| 动作 | 作用 | 是否改变数据库时间线 |
|---|---|---|
BACKUP | 把数据库页写入备份镜像 | 否,只生成恢复材料 |
COMPRESS | 在备份阶段压缩镜像 | 否,只影响镜像大小、CPU 和耗时 |
RESTORE | 把备份镜像中的页还原到目标数据库 | 把数据库放回备份基线 |
ROLLFORWARD | 按顺序重放事务日志,将数据库推进到更晚时间 | 是,沿原日志链向前推进 |
这里是“前滚”,不是事务的“回滚”。ROLLBACK 通常指撤销未提交事务;本文暖备库反复执行的是 ROLLFORWARD。
因此,“备库先应用日志但暂不完成,后面继续追新日志”和“备份是否 COMPRESS”完全是两件事:
- 是否压缩,由
BACKUP DATABASE ... COMPRESS决定。 - 是否保留继续前滚的能力,由 RESTORE 后是否保持
ROLLFORWARD PENDING、前滚时是否省略AND STOP决定。 - 压缩镜像在 RESTORE 时由 DB2 自动解压,RESTORE 和 ROLLFORWARD 没有
COMPRESS开关。
2. 常见备份方式怎么选
| 方式 | 业务停机 | 恢复后前滚 | 日志依赖 | 恢复复杂度 | 适用场景 |
|---|---|---|---|---|---|
| 离线完整备份 | 需要 | 只恢复到备份点时可不前滚 | 立即开放时不依赖;恢复到更晚时间仍需要归档日志 | 低 | 维护窗口、升级前保护、小型数据库、最简单的实验恢复 |
| 在线完整备份并包含日志 | 不需要 | 必须,至少到备份结束点 | 镜像携带到最低一致点所需日志;更晚时间仍需外部日志 | 中 | 生产日常全备、异机恢复基线、接管后的新基线 |
| 在线完整备份但不包含日志 | 不需要 | 必须 | 完全依赖外部连续归档日志 | 中到高 | 已有可靠集中归档、希望控制单个镜像大小 |
在线累计增量 INCREMENTAL | 不需要 | 通常需要 | 依赖完整基线、目标增量镜像和连续日志 | 高 | 数据库很大、每日完整备份窗口不足 |
在线 Delta INCREMENTAL DELTA | 不需要 | 通常需要 | 依赖完整基线、多个 Delta/增量镜像和连续日志 | 很高 | 日变化量小、备份窗口极短且恢复链管理成熟 |
| 表空间在线备份 | 通常不需要全库停机 | 恢复该表空间后需要前滚 | 依赖对应表空间镜像和连续日志 | 高 | 超大库局部保护、单个表空间损坏恢复 |
| 存储快照备份 | 通常很短 | 取决于快照一致性和日志策略 | 强依赖存储平台与日志保护 | 高 | 受支持阵列上的超大数据库、要求极短备份窗口 |
INCREMENTAL 是累计增量,通常包含自最近一次成功完整备份以来改变的页;INCREMENTAL DELTA 是非累计增量,通常只包含自最近一次成功的任意类型备份以来改变的页。Delta 镜像最小,但恢复链更长,任何一个镜像或日志缺失都可能使整条链不可用。
增量备份需要先启用 TRACKMOD YES,并在启用后重新做一次完整备份作为基线。它不是普通完整备份或持续前滚的必需参数。
3. 什么场景使用 COMPRESS
适合压缩备份的情况:
- 备份磁盘容量紧张,保留周期较长。
- 备份需要跨主机、跨机房或经过带宽有限的网络传输。
- 数据可压缩性较好,而且备份时 CPU 有余量。
- 备份落在普通磁盘或 NFS,写入带宽比 CPU 更容易成为瓶颈。
应先压测,甚至考虑不压缩的情况:
- 生产 CPU 已经接近饱和,在线备份不能再明显争抢计算资源。
- 数据主体已经是压缩文件、图片、视频、加密数据或应用层压缩 BLOB,继续压缩收益很低。
- 后端备份设备已经做硬件压缩或重复数据删除,DB2 先压缩可能反而降低设备去重率。
- 首要目标是最短备份或恢复时间,而存储和网络并不紧张。
不能只比较“镜像变小了多少”。正式选型至少要同时记录:备份耗时、恢复耗时、CPU 峰值、平均 I/O、镜像大小和跨机传输耗时。压缩不影响日志能否继续前滚,但恢复压缩镜像时也会消耗 CPU。
COMPRESS 也不等于加密。压缩镜像中的敏感数据仍需通过目录权限、备份介质访问控制或额外加密措施保护。
不压缩时只需省略 COMPRESS:
db2 "backup db LABDB \
to /db2backup/LABDB/offline \
without prompting"4. 什么场景使用 INCLUDE LOGS
INCLUDE LOGS 主要用于在线备份。在线备份期间业务仍在写入,镜像中的不同数据页并非在同一瞬间读取,因此恢复后必须通过日志把它推进到一致点。
使用它的价值是:
- 把使该在线镜像恢复到备份结束点所需的日志一并放进镜像,提高自包含性。
- 异机恢复时,即使外部归档系统暂时不可用,也更容易先恢复到这份备份的最低一致点。
- 适合作为灾备播种、迁移和接管后的新恢复基线。
它的边界是:
- 它不包含备份结束后产生的所有未来日志。要恢复到更晚时间,仍需连续的后续归档日志。
- 在线备份镜像即使包含日志,RESTORE 后仍要执行 ROLLFORWARD,不能使用
WITHOUT ROLLING FORWARD直接开放。 - 还原时可用
LOGTARGET <目录>把镜像内日志抽取出来,再让OVERFLOW LOG PATH指向该目录。 - 离线完整备份本身已经一致,不使用
INCLUDE LOGS;如果要从离线备份继续前滚到更晚时间,依赖的是外部归档日志。
如果企业已有经过校验的集中归档平台,也可以显式使用 EXCLUDE LOGS,让备份镜像和日志分开管理。但恢复演练必须证明:镜像所需的第一份日志到目标时间的最后一份日志都能取回,不能只验证“备份文件存在”。文章中的生产命令显式写出 INCLUDE LOGS 或 EXCLUDE LOGS,避免依赖版本、分区方式和备份类型之间可能不同的默认行为。
5. BACKUP DATABASE 常用参数
DB2 9.7 对参数顺序敏感,先以目标服务器本机帮助为准:
db2 "? BACKUP DATABASE"| 参数 | 作用 | 适用场景 | 关键边界 |
|---|---|---|---|
ONLINE | 业务在线时备份 | 生产日常备份 | 数据库必须启用归档日志,恢复后必须前滚 |
不写 ONLINE | 离线备份 | 维护窗口、最简单的一致性快照 | 备份前要断开连接并停用数据库 |
TABLESPACE (...) | 只备份指定表空间 | 超大库局部保护 | 恢复依赖表空间设计、历史和日志,不能替代完整基线 |
INCREMENTAL | 累计增量 | 减少日常备份量 | 需要 TRACKMOD YES 和完整基线 |
INCREMENTAL DELTA | 非累计增量 | 最小化单次备份量 | 恢复链最长,必须定期做完整恢复演练 |
TO <目录> | 写入一个或多个磁盘目录 | 磁盘备份 | 多个 TO 路径是分条带写入,不是自动生成多份副本 |
USE TSM / XBSA / LOAD | 使用备份管理器或厂商库 | 企业备份平台 | 需要单独验证代理、库文件、凭据和介质可恢复性 |
COMPRESS | 压缩备份镜像 | 节省容量和传输带宽 | 增加 CPU 开销;DB2 9.7 中要写在 INCLUDE LOGS 前 |
INCLUDE LOGS | 在在线镜像中包含到备份结束点所需日志 | 异机恢复、灾备播种 | 不包含备份后的未来日志 |
EXCLUDE LOGS | 不把日志放进镜像 | 外部归档体系可靠 | 恢复端必须另行取得完整连续日志 |
WITH n BUFFERS | 指定备份缓冲区数量 | 性能调优 | 默认由 DB2 计算,手工值必须压测 |
BUFFER n | 指定每个缓冲区大小,单位为 4 KB 页 | 性能调优 | 不是字节数,盲目增大可能挤占内存 |
PARALLELISM n | 指定并行读取表空间的数量 | 多表空间、多磁盘 | 过高会放大 CPU 和 I/O 竞争 |
UTIL_IMPACT_PRIORITY n | 限制在线工具对业务的影响,范围 1~100 | 高峰期在线备份 | 只有实例启用 UTIL_IMPACT_LIM 后才真正节流 |
WITHOUT PROMPTING | 禁止交互式介质提示 | 脚本和无人值守任务 | 失败时要依靠退出码、历史和日志告警 |
6. RESTORE DATABASE 常用参数
db2 "? RESTORE DATABASE"| 参数 | 作用 | 适用场景 | 关键边界 |
|---|---|---|---|
FROM <目录> | 指定镜像所在目录或介质 | 所有磁盘恢复 | 写目录,不写完整镜像文件名 |
TAKEN AT <时间戳> | 选择具体备份镜像 | 同目录存在多份备份 | 建议固定写完整 14 位时间戳 |
TO <目录> | 改变目标数据库目录 | 非自动存储或只改 database directory | 对自动存储不会同时改变 storage paths |
ON <路径> | 重定义自动存储路径 | 异机、磁盘布局变化 | 可配合 DBPATH ON <路径> 单独指定数据库目录 |
DBPATH ON <路径> | 指定数据库目录 | 异机恢复 | 与数据容器路径不是同一个概念 |
INTO <新别名> | 恢复为其他数据库名 | 克隆、实验、迁移验证 | 目标名称必须唯一,应用连接串也要对应修改 |
LOGTARGET <目录> | 从包含日志的镜像中抽取日志 | 在线备份恢复 | 不是活动日志路径,也不会自动成为前滚搜索路径 |
NEWLOGPATH <目录> | 指定恢复后的活动日志路径 | 异机、改磁盘布局 | 不负责查找归档日志,不要假定 DB2 会替你补齐 NODE0000 层级,恢复后要核验实际路径 |
WITHOUT ROLLING FORWARD | 恢复一致的离线镜像后立即结束恢复链 | 只需要回到离线备份时刻 | 在线备份镜像不能使用;需要恢复到更晚时间时也不能使用 |
REPLACE EXISTING | 覆盖已有目标数据库 | 明确批准的原位重建 | 破坏性参数,使用前必须确认目标别名和路径 |
REDIRECT | 进入重定向恢复,重新指定表空间容器 | 非自动存储、容器路径变化 | SET TABLESPACE CONTAINERS 和 RESTORE ... CONTINUE 要在同一恢复流程完成 |
REDIRECT GENERATE SCRIPT | 生成可审阅的重定向恢复脚本 | 复杂异机迁移 | 先审阅所有路径,再作为一个 CLP 脚本执行 |
INCREMENTAL AUTOMATIC | 让 DB2 按历史自动恢复增量链 | 增量恢复 | 所需基线和增量镜像必须完整且可定位 |
TABLESPACE (...) [ONLINE] | 恢复指定表空间 | 局部损坏 | 后续仍要做表空间前滚 |
COMPRLIB / COMPROPTS | 指定自定义压缩库及参数 | 使用非默认压缩库 | 普通 COMPRESS 镜像自动解压,不需要再写 COMPRESS |
WITHOUT PROMPTING | 禁止交互式介质提示 | 自动化恢复 | 必须检查命令退出码和恢复状态 |
LOGTARGET INCLUDE | EXCLUDE [FORCE] 是快照恢复的日志卷处理方式,不是磁盘备份镜像的“强制应用日志”开关。普通 INCLUDE LOGS 镜像优先使用显式、空的 LOGTARGET <目录>,避免日志文件名冲突。
7. ROLLFORWARD DATABASE 常用参数
db2 "? ROLLFORWARD DATABASE"| 参数 | 作用 | 适用场景 | 关键边界 |
|---|---|---|---|
QUERY STATUS | 查看当前前滚位置 | 每轮前滚前后 | 结合 processed range、commit time 和 pending 状态判断 |
TO END OF BACKUP | 前滚到在线备份的最低一致点 | 只恢复到备份结束点 | 常与镜像内日志和 LOGTARGET 配合 |
TO END OF LOGS | 应用当前能够取得的全部连续日志 | 灾难恢复、暖备追赶 | 只能到可见日志末尾,不能证明尾日志没有遗漏 |
TO <isotime> | 恢复到指定时间点 | 误删除、误更新、延迟恢复 | 默认按 UTC;输入服务器本地时间必须写 USING LOCAL TIME |
USING UTC TIME | 按 UTC 解释目标或显示状态 | 跨时区、主备时区不一致 | 推荐在自动化流程中统一使用 |
USING LOCAL TIME | 按数据库服务器本地时间解释 | 人工按本地业务时间定位 | 必须先确认时区和时钟同步 |
不写 AND STOP | 应用日志后继续保持前滚暂挂 | 持续暖备、多轮追日志 | 数据库仍不能普通连接,但后面可继续前滚 |
AND STOP / AND COMPLETE | 结束前滚、回滚未完成事务并开放数据库 | 最终恢复或接管 | 执行后不能沿本次恢复过程继续追加日志 |
OVERFLOW LOG PATH (...) | 增加一个明确的日志查找目录 | 手工传送归档日志 | 不会改变活动日志或归档配置 |
NORETRIEVE | 禁止通过 LOGARCHMETH 自动取回日志 | 只允许使用人工校验后的日志 | 日志缺失时不会帮你从归档系统补取 |
CANCEL | 放弃当前前滚恢复 | 恢复链确认无法继续且准备重做 RESTORE | 不是正常完成,通常会进入 Restore Pending |
TABLESPACE (...) | 只前滚指定表空间 | 表空间恢复 | 必须保证该表空间所需日志连续 |
RECOVER DROPPED TABLE | 从日志恢复满足前置条件的误删表 | 表级误删除 | 必须在删除前启用相应恢复能力,并先从历史中取得 dropped-table-id |
还有一个容易忽略的限制:同一次恢复流程一旦按 TO END OF LOGS 向前推进,就不能再改成更早的指定时间点恢复。若决定改做 PITR,必须重新 RESTORE 基线镜像,再按目标时间前滚。
8. “主动归档”和“强制应用日志”不是一回事
db2 "archive log for database LABDB"这条命令是在源库主动切换当前日志并触发归档,便于把一份已经闭合的日志文件传送出去。它不会在备库应用日志,也不能补回已经丢失的日志。
真正应用日志的是 ROLLFORWARD。DB2 没有安全参数可以:
- 跳过缺失的
S0000007.LOG,直接应用S0000008.LOG。 - 把其他数据库、其他日志链或损坏的日志强行套到当前恢复链。
- 忽略日志校验或把未闭合的活动日志当成完整归档日志。
OVERFLOW LOG PATH 只是告诉 DB2 到哪里找日志,NORETRIEVE 只是禁止自动取回;两者都不会降低连续性和日志链校验要求。
五、创建实验数据库和独立日志路径
创建数据库:
db2 "create db LABDB \
automatic storage yes \
on /db2data \
dbpath on /db2data \
using codeset GBK \
territory CN \
collate using system \
pagesize 4 K \
dft_extent_sz 32"准备日志与备份目录:
mkdir -p /db2data/onlinelog/LABDB
mkdir -p /db2data/mirlog/LABDB
mkdir -p /db2backup/LABDB/archive
chmod 750 /db2data/onlinelog/LABDB
chmod 750 /db2data/mirlog/LABDB
chmod 750 /db2backup/LABDB/archive本实验为了接近现有生产参数,设置了较大的日志配置:
db2 "update db cfg for LABDB using UTIL_HEAP_SZ 524288 DEFERRED"
db2 "update db cfg for LABDB using LOCKLIST 19328 DEFERRED"
db2 "update db cfg for LABDB using MAXLOCKS 98 DEFERRED"
db2 "update db cfg for LABDB using TRACKMOD YES DEFERRED"
db2 "update db cfg for LABDB using LOGFILSIZ 10000 DEFERRED"
db2 "update db cfg for LABDB using LOGPRIMARY 50 DEFERRED"
db2 "update db cfg for LABDB using LOGSECOND 100 DEFERRED"
db2 "update db cfg for LABDB using NEWLOGPATH /db2data/onlinelog/LABDB DEFERRED"
db2 "update db cfg for LABDB using MIRRORLOGPATH /db2data/mirlog/LABDB DEFERRED"其中 TRACKMOD YES 用于跟踪发生变化的页面,为后续增量备份提供条件。它不是离线完整备份、在线完整备份或日志前滚的必要参数;如果刚从 NO 改为 YES,应在配置生效后重新建立一份非增量完整备份,才能开始新的增量链。
LOGFILSIZ=10000 在 4 KB 日志页下约为 40 MB,LOGPRIMARY=50 会预分配约 2 GB 主日志;镜像日志还会再占用约 2 GB。不要在空间不足的环境中直接照抄。
让延迟配置生效:
db2 terminate
db2 deactivate db LABDB
db2 activate db LABDB检查实际路径:
db2 get db cfg for LABDB | \
egrep -i "pending|Path to log files|Mirror log path"还应检查在线日志和镜像日志目录中是否都生成了实际日志文件。
六、创建可验证的基线业务数据
连接数据库并创建测试表:
db2 connect to LABDBdb2 "create table DB2INST1.DR_ORDERS (
ORDER_ID integer not null,
ORDER_NO varchar(32) not null,
PHASE varchar(20) not null,
AMOUNT decimal(12,2) not null,
NOTE varchar(128),
CREATED_AT timestamp not null default current timestamp,
constraint PK_DR_ORDERS primary key (ORDER_ID)
)"插入三条离线备份基线:
db2 "insert into DB2INST1.DR_ORDERS
(ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE)
values (1, 'ORDER-0001', 'BASELINE', 100.00, 'before offline backup')"
db2 "insert into DB2INST1.DR_ORDERS
(ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE)
values (2, 'ORDER-0002', 'BASELINE', 200.00, 'before offline backup')"
db2 "insert into DB2INST1.DR_ORDERS
(ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE)
values (3, 'ORDER-0003', 'BASELINE', 300.00, 'before offline backup')"后续每批日志都会修改或新增不同的订单,因此可以明确判断恢复到了哪个阶段。
七、第一阶段:离线全备与快照恢复
1. 确认数据库已经停用
db2 connect reset
db2 terminate
db2 deactivate db LABDB
db2 list active databases这里是 databases 复数。写成 db2 list active database 会返回 SQL0104N。
2. 执行压缩离线全备
mkdir -p /db2backup/LABDB/offline
chmod 750 /db2backup/LABDB/offline
time db2 "backup db LABDB \
to /db2backup/LABDB/offline \
compress \
without prompting"本次实验的压缩离线全备约 65 MB,耗时约 4 秒。实际环境的耗时取决于数据库规模、存储吞吐、压缩开销和并发负载。
查看历史:
db2 list history backup all for LABDB记录备份时间戳和镜像文件名。跨主机传输前计算 SHA-256,并使用 DB2 自带工具检查镜像:
sha256sum /db2backup/LABDB/offline/LABDB*.001
db2ckbkp -h /db2backup/LABDB/offline/LABDB*.001应看到:
Image Verification Complete - successful3. 制造备份后的变化
db2 connect to LABDBdb2 "update DB2INST1.DR_ORDERS
set PHASE='AFTER_BACKUP',
AMOUNT=999.99,
NOTE='row changed after offline backup'
where ORDER_ID=1"
db2 "insert into DB2INST1.DR_ORDERS
(ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE)
values (4, 'ORDER-0004', 'AFTER_BACKUP', 400.00,
'row created after offline backup')"此时主库有 4 行;但离线备份中仍只有原来的 3 行。
4. 传送并校验镜像
先在备库建立目标目录:
mkdir -p /db2backup/LABDB/offline
chmod 750 /db2backup/LABDB/offline在主库传送:
rsync -avh \
--progress \
--partial \
/db2backup/LABDB/offline/LABDB.0.db2inst1.NODE0000.CATN0000.<备份时间戳>.001 \
db2inst1@192.0.2.20:/db2backup/LABDB/offline/这是为了复现实验过程而保留的人工命令。生产自动化不应让未完成的文件直接使用正式镜像名,应先传为 .part,完成大小、SHA-256 和 db2ckbkp 校验后再原子改名。
在备库重新执行:
sha256sum /db2backup/LABDB/offline/LABDB*.001
db2ckbkp -h /db2backup/LABDB/offline/LABDB*.001不能只看 rsync 显示 100%。SHA-256 用于判断传输内容是否一致,db2ckbkp 用于判断 DB2 媒体头和备份结构是否有效。
5. 恢复为可立即连接的快照
备库准备日志路径:
mkdir -p /db2data/onlinelog/LABDB
mkdir -p /db2data/mirlog/LABDB/NODE0000
chmod 750 /db2data/onlinelog/LABDB
chmod 750 /db2data/mirlog/LABDB
chmod 750 /db2data/mirlog/LABDB/NODE0000恢复命令:
time db2 "restore db LABDB \
from /db2backup/LABDB/offline \
taken at <备份时间戳> \
on /db2data \
dbpath on /db2data \
newlogpath /db2data/onlinelog/LABDB \
without rolling forward \
without prompting"这里能够使用 WITHOUT ROLLING FORWARD,是因为恢复对象是一份一致的离线完整备份,而且目标只要求回到备份时刻。它表示恢复完成后不保持前滚暂挂,数据库可以立即连接。
在线备份镜像不能靠这个参数直接开放;如果还要从离线备份继续恢复到备份后的某个时间,也必须省略它并执行 ROLLFORWARD。
验证:
db2 connect to LABDB
db2 "select ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE
from DB2INST1.DR_ORDERS
order by ORDER_ID"正确结果应只有 3 行:
- 第 1 行仍是
BASELINE / 100.00。 - 不存在第 4 行。
Backup pending = NO。Rollforward pending = NO。
这证明离线全备恢复得到的是备份时刻的一致性快照,而不是主库当前状态。
八、第二阶段:启用归档日志并制作备机播种备份
1. 从循环日志切换到归档日志
先在主库准备目录:
mkdir -p /db2backup/LABDB/archive
mkdir -p /db2backup/LABDB/standby_seed
chmod 750 /db2backup/LABDB/archive
chmod 750 /db2backup/LABDB/standby_seed启用磁盘归档:
db2 "update db cfg for LABDB using \
LOGARCHMETH1 DISK:/db2backup/LABDB/archive \
DEFERRED"Linux 路径区分大小写。如果目录实际为 /db2backup/LABDB/archive,配置却写成 /db2backup/labdb/archive,DB2 9.7 会返回 SQL5099N reason code 2。
断开连接并使延迟配置生效:
db2 connect reset
db2 terminate
db2 deactivate db LABDB从循环日志切换到归档日志后,DB2 需要一份新的完整备份建立恢复基线。本实验使用压缩离线全备:
time db2 "backup db LABDB \
to /db2backup/LABDB/standby_seed \
compress \
without prompting"确认:
db2 get db cfg for LABDB | \
egrep -i "Backup pending|Rollforward pending|First log archive method|First active log file"应看到:
Backup pending = NO
Rollforward pending = NO
First log archive method = DISK:/db2backup/LABDB/archive/
First active log file = S0000000.LOG再次对播种镜像执行 SHA-256 和 db2ckbkp,然后传送到备库。
九、生成第一批归档日志
播种备份完成后,在主库制造第一批变化,例如更新第 2 行并插入第 5 行。
提交完成后必须先断开当前 CLP 连接,再执行主动归档:
db2 connect reset
db2 terminate
db2 "archive log for database LABDB"生产中不能只看到 DB20000I 就立刻传送文件。应继续确认归档状态成功、目标文件已经出现且大小稳定,再计算校验和。ARCHIVE LOG 的用途是主动切换当前日志并触发归档,不代表跨主机传输已经完成。
如果 CLP 仍连接着数据库,ARCHIVE LOG 或 DEACTIVATE DATABASE 会返回:
SQL1493N The application is already connected to an active database.查看归档目录:
find /db2backup/LABDB/archive \
-type f \
-name 'S*.LOG' \
-printf '%f %s bytes %p\n' |
sortDB2 会自动生成类似目录:
/db2backup/LABDB/archive/
└── db2inst1/LABDB/NODE0000/C0000000/
├── S0000000.LOG
└── S0000001.LOG主动切换产生的归档日志可能只有 12 KB,而在线日志文件预分配约 40 MB。这不代表日志损坏:归档文件大小取决于日志切换前实际写入的页数,应以序号连续、校验和、归档状态和前滚结果判断。
十、恢复备库并保持 ROLLFORWARD PENDING
1. 传送播种备份和连续日志
备库准备目录:
mkdir -p /db2backup/LABDB/standby_seed
mkdir -p /db2backup/LABDB/rollforward_logs
chmod 750 /db2backup/LABDB/standby_seed
chmod 750 /db2backup/LABDB/rollforward_logs传送备份镜像和日志:
rsync -avh --progress \
/db2backup/LABDB/standby_seed/LABDB*.001 \
db2inst1@192.0.2.20:/db2backup/LABDB/standby_seed/
rsync -avh --progress \
/db2backup/LABDB/archive/db2inst1/LABDB/NODE0000/C0000000/ \
db2inst1@192.0.2.20:/db2backup/LABDB/rollforward_logs/在备库校验每个文件的 SHA-256。
2. 中断传输可能留下零字节镜像
本次实验曾误触重新传输并中断,目标备份文件被留下为 0 字节。恢复时报错:
SQL2068N An invalid image was encountered ... There was no media header.此时不要反复修改 RESTORE 参数。先检查:
stat /db2backup/LABDB/standby_seed/LABDB*.001
sha256sum /db2backup/LABDB/standby_seed/LABDB*.001
db2ckbkp -h /db2backup/LABDB/standby_seed/LABDB*.001零字节文件的 SHA-256 固定为:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855确认源镜像正常后,删除明确的空文件并完整重传。不要在无法确认文件状态时盲目使用续传参数。
3. 恢复但不结束前滚
如果备库已存在前一阶段的 LABDB,只在确认它是可删除的实验库后执行:
db2 connect reset
db2 terminate
db2 deactivate db LABDB
db2 drop db LABDB清理并重建专属日志目录:
rm -rf -- /db2data/onlinelog/LABDB
rm -rf -- /db2data/mirlog/LABDB
mkdir -p /db2data/onlinelog/LABDB
mkdir -p /db2data/mirlog/LABDB/NODE0000
chmod 750 /db2data/onlinelog/LABDB
chmod 750 /db2data/mirlog/LABDB
chmod 750 /db2data/mirlog/LABDB/NODE0000恢复命令中故意省略 WITHOUT ROLLING FORWARD:
time db2 "restore db LABDB \
from /db2backup/LABDB/standby_seed \
taken at <播种备份时间戳> \
on /db2data \
dbpath on /db2data \
newlogpath /db2data/onlinelog/LABDB \
without prompting"检查:
db2 get db cfg for LABDB | \
egrep -i "Backup pending|Rollforward pending|Restore pending"
db2 "rollforward db LABDB query status"DB2 9.7 的典型结果为:
Rollforward pending = DATABASE
Rollforward status = DB pending
Next log file to be read = S0000000.LOG这里的 DATABASE 表示整个数据库处于前滚暂挂,不是异常值。
尝试连接应返回:
SQL1117N ... because of ROLL-FORWARD PENDING这正是暖备库需要保持的状态。
十一、多轮应用日志但不执行 STOP
第一次应用当前已有日志:
time db2 "rollforward db LABDB \
to end of logs \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"注意命令中没有 AND STOP。
查询状态:
db2 "rollforward db LABDB query status"本次实验第一次前滚后显示:
Rollforward status = DB working
Log files processed = S0000000.LOG - S0000001.LOG
Last committed transaction = 逐步向后推进数据库仍不能连接,但可以继续把后续归档日志传入指定目录,并再次执行不带 AND STOP 的前滚。
在主库生成第二批事务并执行 ARCHIVE LOG 后,只传送新的 S0000002.LOG:
rsync -avh --progress \
/db2backup/LABDB/archive/db2inst1/LABDB/NODE0000/C0000000/S0000002.LOG \
db2inst1@192.0.2.20:/db2backup/LABDB/rollforward_logs/备库重复执行同一条不带 STOP 的前滚命令。处理范围会推进到:
S0000000.LOG - S0000002.LOG本环境在 DB working 状态下,Next log file to be read 仍可能显示最后处理到的日志,例如 S0000002.LOG。不要只看这一行,应同时检查:
Log files processed是否推进。Last committed transaction是否变晚。Rollforward pending是否仍为DATABASE。- 普通连接是否仍被
SQL1117N阻止。
十二、为什么持续前滚能缩短最终恢复时间
如果备库只恢复一次全备,却长期不应用日志,故障时需要一次性处理大量归档日志,恢复时间不可控。
持续前滚的思路是:
- 主库正常运行并持续归档日志。
- 归档日志按固定周期传送到备库。
- 备库反复执行
TO END OF LOGS,但不执行STOP。 - 切换前再做一次预同步,让备库追到最近的完整日志。
- 正式停写后只传送最后一小段尾日志。
本次实验每次前滚约为 0.6 秒。切换前备库已处理到 S0000003.LOG,正式停写后只需要传送并应用 S0000004.LOG。
十三、最终切换前检查
1. 检查两机时钟
RTO 计时依赖两机时钟。至少执行:
date '+%F %T.%N %z'正式生产还应检查 NTP 或 Chrony 的持续同步状态,不能只依赖一次 date 取样。
2. 备库必须提前准备接管后的归档目录
备库会继承主库的 LOGARCHMETH1。如果配置为:
DISK:/db2backup/LABDB/archive/那么备库在执行 AND STOP 前必须存在该目录:
mkdir -p /db2backup/LABDB/archive
chmod 750 /db2backup/LABDB/archive同时检查:
db2 get db cfg for LABDB | \
egrep -i "LOGARCHMETH1|Path to log files|Mirror log path|pending"3. 冻结旧主库,避免双主
有计划切换时,先停止应用写入,再断开 DB2 会话:
db2 connect reset
db2 terminate记录停写时间后,主动切换当前日志并触发最后尾日志归档,再停用数据库:
date '+PRIMARY_WRITE_STOP_EPOCH=%s.%N PRIMARY_WRITE_STOP=%F %T.%N %z'
db2 "archive log for database LABDB"
db2 deactivate db LABDB
date '+PRIMARY_QUIESCED_EPOCH=%s.%N PRIMARY_QUIESCED=%F %T.%N %z'
db2 list active databases如果主库仍可能被其他应用重新连接,仅执行 DEACTIVATE 还不等于完整的生产隔离。实际切换还需要停止应用、收回访问入口、断开网络或执行其他 fencing 措施。
十四、传送尾日志并执行最终接管
在主库计算尾日志校验和并传送:
sha256sum \
/db2backup/LABDB/archive/db2inst1/LABDB/NODE0000/C0000000/S0000004.LOG
rsync -avh --progress \
/db2backup/LABDB/archive/db2inst1/LABDB/NODE0000/C0000000/S0000004.LOG \
db2inst1@192.0.2.20:/db2backup/LABDB/rollforward_logs/备库校验后记录恢复开始时间:
date '+STANDBY_FINAL_START_EPOCH=%s.%N STANDBY_FINAL_START=%F %T.%N %z'执行最终前滚:
time db2 "rollforward db LABDB \
to end of logs \
and stop \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"AND STOP 会结束当前前滚恢复,回滚尚未完成的事务,并使数据库脱离 ROLLFORWARD PENDING。在本文暖备架构中,这一步就是不可逆的角色转换点;执行后数据库可以正常连接,但不能继续按原恢复过程追加日志。
连接并记录可用时间:
db2 connect to LABDB
date '+STANDBY_READY_EPOCH=%s.%N STANDBY_READY=%F %T.%N %z'验证业务数据和状态:
db2 "select ORDER_ID, ORDER_NO, PHASE, AMOUNT, NOTE, CREATED_AT
from DB2INST1.DR_ORDERS
order by ORDER_ID"
db2 get db cfg for LABDB | \
egrep -i "Backup pending|Rollforward pending|Restore pending|LOGARCHMETH1|Path to log files|Mirror log path"本次最终结果:
Rollforward status = not pending
Log files processed = S0000000.LOG - S0000004.LOG
Backup pending = NO
Rollforward pending = NO
Restore pending = NO最终的第 8 行交易也存在,说明最后一个已提交事务已经恢复。
十五、本次实验的 RPO 与 RTO
实测结果:
| 指标 | 实测值 | 说明 |
|---|---|---|
| 离线全备 | 约 4 秒 | 小型压缩实验库 |
| 普通离线恢复 | 约 3.6 秒 | 恢复后立即可连接 |
| 播种备份恢复 | 约 2.3 秒 | 恢复后保持前滚暂挂 |
| 单轮持续前滚 | 约 0.6 秒 | 每轮只处理少量新日志 |
| 最终尾日志前滚并 STOP | 0.504 秒 | DB2 恢复引擎耗时 |
| 最终前滚开始到连接成功 | 19.151 秒 | 包含命令结束和连接验证 |
| 主库停写到备库连接成功 | 121.011 秒 | 包含人工传输、等待和交互 |
本次为有计划切换,最终归档日志可正常取得,第 8 行最终交易成功恢复,因此:
RPO = 0需要区分两个 RTO:
- DB2 引擎本身完成尾日志应用和
STOP只用了约 0.5 秒。 - 端到端停机约 121 秒,主要时间消耗在人工输入、密码交互、文件传输和验证。
生产优化的重点通常不是继续缩短这 0.5 秒,而是自动化停写确认、日志传送、校验、前滚、连接切换和业务验证。
十六、接管后的新日志链检查
执行 AND STOP 后,新主库会生成新的日志链。例如原日志链为:
C0000000接管后的新日志链可能变为:
C0000001本次接管后首次执行 db2pd -db LABDB -logs,曾看到:
Method 1 Archive Status = Failuredb2diag.log 显示 DB2 尝试从活动日志和镜像日志目录查找前滚使用过的旧日志,但这些日志来自 OVERFLOW LOG PATH。诊断日志随后记录:
Assume log was archived and continue.这属于新日志链启动时的过渡检查。主动归档新主库的第一份本地日志:
db2 connect reset
db2 terminate
db2 "archive log for database LABDB"检查:
find /db2backup/LABDB/archive/db2inst1/LABDB/NODE0000/C0000001 \
-type f \
-name 'S*.LOG' \
-printf '%f %s bytes %p\n'
db2 activate db LABDB
db2pd -db LABDB -logs | sed -n '1,18p'本次最终状态为:
S0000005.LOG 已归档到 C0000001
Current active log = S0000006.LOG
Method 1 Archive Status = Success
Method 1 Next Log to Archive = 6
Log Chain ID = 1只有数据可查询还不够,接管后的在线日志、镜像日志和归档日志都必须继续正常工作。
十七、接管后立即建立新恢复基线
新主库已经进入新的日志链,应尽快执行新的完整备份。
DB2 9.7 的参数顺序应以本机帮助为准:
db2 "? BACKUP DATABASE"本版本要求 COMPRESS 位于 INCLUDE LOGS 前面:
mkdir -p /db2backup/LABDB/post_cutover_full
chmod 750 /db2backup/LABDB/post_cutover_full
time db2 "backup db LABDB online \
to /db2backup/LABDB/post_cutover_full \
compress \
include logs \
without prompting"写成以下顺序会报 SQL0104N:
ONLINE ... INCLUDE LOGS COMPRESS备份后检查:
db2 list history backup all for LABDB
sha256sum /db2backup/LABDB/post_cutover_full/LABDB*.001
db2ckbkp -h /db2backup/LABDB/post_cutover_full/LABDB*.001本次接管后在线全备的结果:
Backup Mode = 1
Includes Logs = 1
Compression = 1
Image Verification Complete = successful这份备份以新主库的新日志链为基线。镜像包含了恢复到该在线备份结束点所需的日志,但要恢复到更晚时间,仍然需要新日志链上连续的后续归档日志。
十八、常见备份恢复场景命令速查
前面的离线快照恢复、持续暖备和最终接管均为本次实际执行并取得输出的实验。本节其余命令是依据 DB2 9.7 FP6 本机帮助整理的通用模板,尚未在本文实验中逐项执行,投入生产前必须用同版本、同存储类型的副本做完整恢复演练。
下面的 <备份时间戳> 均指 DB2 备份返回的 14 位时间戳,例如 20260731173354;<目标时间> 必须替换为实际恢复点。
1. 离线完整备份恢复后立即开放
适用条件:镜像来自离线完整备份,目标只需要回到备份时刻,不需要继续应用备份后的日志。
db2 "restore db LABDB \
from /db2backup/LABDB/offline \
taken at <备份时间戳> \
on /db2data \
dbpath on /db2data \
newlogpath /db2data/onlinelog/LABDB \
without rolling forward \
without prompting"如果镜像来自在线备份,不得照抄 WITHOUT ROLLING FORWARD;DB2 9.7 会拒绝这种用法。
2. 在线完整备份包含日志,恢复到备份结束点
先生成镜像:
db2 "backup db LABDB online \
to /db2backup/LABDB/online_full \
compress \
include logs \
without prompting"恢复时把镜像内日志抽取到独立空目录:
mkdir -p /db2backup/LABDB/image_logs
chmod 750 /db2backup/LABDB/image_logs
db2 "restore db LABDB \
from /db2backup/LABDB/online_full \
taken at <备份时间戳> \
on /db2data \
dbpath on /db2data \
logtarget /db2backup/LABDB/image_logs \
newlogpath /db2data/onlinelog/LABDB \
without prompting"只恢复到该在线备份的最低一致点:
db2 "rollforward db LABDB \
to end of backup \
and stop \
overflow log path (/db2backup/LABDB/image_logs) \
noretrieve"TO END OF BACKUP 不是“恢复到当前最新时间”。它只使用镜像携带的日志把在线备份变成可用的一致数据库。
3. 在线备份不包含日志,使用外部归档日志恢复
当归档日志已由集中平台可靠保管时,可以让镜像和日志分开:
db2 "backup db LABDB online \
to /db2backup/LABDB/online_full \
compress \
exclude logs \
without prompting"RESTORE 时不写 LOGTARGET,随后把外部取得的连续日志放入专用目录:
db2 "restore db LABDB \
from /db2backup/LABDB/online_full \
taken at <备份时间戳> \
on /db2data \
dbpath on /db2data \
newlogpath /db2data/onlinelog/LABDB \
without prompting"
db2 "rollforward db LABDB \
to end of logs \
and stop \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"这里的关键风险不是镜像本身,而是外部归档日志是否从第一份所需日志起连续无缺口。执行最终 STOP 前必须确认最后提交时间符合预期。
4. 异机改路径,并恢复为新的数据库名
下面示例假设源镜像是离线完整备份,源数据库名为 LABDB,目标别名改为 LABCLONE:
db2 "restore db LABDB \
from /db2backup/LABDB/offline \
taken at <备份时间戳> \
on /db2data/labclone \
dbpath on /db2data/labclone \
into LABCLONE \
newlogpath /db2data/onlinelog/LABCLONE \
without rolling forward \
without prompting"INTO 只改变目标数据库别名,不会自动重命名或重写以下内容:
- Schema、表空间、授权 ID 和对象所有者。
LOGARCHMETH1、MIRRORLOGPATH和外部归档目标。- 外部表、用户自定义函数、存储过程库、裸设备和应用连接配置。
如果源镜像是在线备份,应去掉 WITHOUT ROLLING FORWARD,再按日志来源执行前滚。
5. 恢复到误操作之前的指定时间点
先恢复一份早于误操作时间的可恢复备份,并保持 ROLLFORWARD PENDING。然后使用明确时区的目标时间:
db2 "rollforward db LABDB \
to 2026-07-31-17.18.00 \
using local time \
and stop \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"这条命令中的时间只是格式示例,不能直接用于其他环境。生产操作必须确认:
- 目标时间早于错误事务提交时间,而不是早于操作员发现时间。
USING LOCAL TIME使用的是数据库服务器本地时间;默认解释为 UTC。- 主备时区、NTP 状态和业务记录时间一致。
- 目标时间不早于在线备份允许的最小恢复时间。
- 从备份基线到目标时间的所有日志连续可用。
同一次恢复流程一旦已经使用 TO END OF LOGS,不能再改为更早的时间点恢复。要改变目标时间,必须重新 RESTORE 基线镜像。
6. 持续暖备与生产最终接管
持续追日志但不开放数据库:
db2 "rollforward db LABDB \
to end of logs \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"本文实验为了测量一次命令的最终耗时,使用了 TO END OF LOGS AND STOP。生产接管时,更稳妥的方式是先应用尾日志并检查,再单独结束前滚:
db2 "rollforward db LABDB \
to end of logs \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"
db2 "rollforward db LABDB query status using local time"
db2 "rollforward db LABDB stop"只有确认日志处理范围、最后提交时间和源库停写点一致后,才能执行最后一条 STOP。如果已经达到最低一致恢复点但尾日志永久缺失,业务只能选择在最后一个正常恢复点结束并接受相应 RPO,或重新选择其他备份基线;不能把缺失日志“强制补过”。
7. 累计增量和 Delta 备份恢复
启用 TRACKMOD YES 并生效后,先建立新的非增量完整基线,再生成增量镜像:
db2 "backup db LABDB online \
to /db2backup/LABDB/incremental_chain \
compress \
include logs \
without prompting"
db2 "backup db LABDB online incremental \
to /db2backup/LABDB/incremental_chain \
compress \
include logs \
without prompting"
db2 "backup db LABDB online incremental delta \
to /db2backup/LABDB/incremental_chain \
compress \
include logs \
without prompting"当完整基线、所有所需增量镜像和恢复历史都能被 DB2 找到时,可优先使用自动增量恢复:
mkdir -p /db2backup/LABDB/incremental_logs
chmod 750 /db2backup/LABDB/incremental_logs
db2 "restore db LABDB incremental automatic \
from /db2backup/LABDB/incremental_chain \
taken at <目标增量镜像时间戳> \
on /db2data \
dbpath on /db2data \
logtarget /db2backup/LABDB/incremental_logs \
newlogpath /db2data/onlinelog/LABDB \
without prompting"恢复在线增量镜像后仍要前滚。示例中的 LOGTARGET 用于抽取镜像所含日志;如果目标时间晚于最后一份增量备份,还要补齐之后的连续归档日志。手工增量恢复的镜像调用顺序比较反直觉,本文不提供未经实验验证的复制脚本;生产中必须验证自动选链结果,并定期证明整条链能够从零恢复。
8. 表空间级备份与恢复
适用于局部表空间损坏,而不是整库灾难:
db2 "backup db LABDB \
tablespace (TS_DATA) \
online \
to /db2backup/LABDB/tablespace \
compress \
without prompting"
db2 "restore db LABDB \
tablespace (TS_DATA) \
online \
from /db2backup/LABDB/tablespace \
taken at <备份时间戳> \
without prompting"
db2 "rollforward db LABDB \
to end of logs \
and stop \
tablespace (TS_DATA) \
online \
overflow log path (/db2backup/LABDB/rollforward_logs) \
noretrieve"表空间恢复仍需评估系统目录、LOB、索引、长数据和跨表空间对象依赖。本次实验没有执行表空间恢复,这组命令只能作为 DB2 9.7 语法模板,不能替代实际演练。
9. 非自动存储或容器路径变化:重定向恢复
自动存储数据库只改变存储路径时,优先考虑 ON ... DBPATH ON ...。DMS/SMS 容器需要逐个改路径时,才进入正式的重定向恢复流程:
db2 "restore db LABDB \
from /db2backup/LABDB/offline \
taken at <备份时间戳> \
redirect generate script /tmp/restore-LABDB.clp \
without prompting"先审阅生成脚本中的所有目标路径、容器和 REPLACE EXISTING 风险,再将 RESTORE ... REDIRECT、SET TABLESPACE CONTAINERS 和 RESTORE ... CONTINUE 作为一个完整 CLP 流程执行:
db2 -tvf /tmp/restore-LABDB.clp不要把重定向恢复的三个阶段拆到彼此无关的一次性远程会话中。
10. 缺日志、坏日志和错误日志链怎么处理
| 状态 | 正确处理 |
|---|---|
QUERY STATUS 指向一份尚未到达的日志 | 保持 Pending,等待或补传该精确序号,然后重复前滚 |
| 后一序号已存在,但中间缺一份 | 不能跳过,必须找回缺失日志或更换恢复基线 |
| 同名日志来自其他数据库或其他日志链 | 不能混用,即使文件名和序号相同 |
| 日志文件损坏 | 用同一日志链的正常副本替换后继续 |
| 尾日志永久无法取得 | 评估可接受的数据损失,在最后正常点 STOP,或重新选择备份恢复 |
误用了错误的目标时间或已走过 END OF LOGS | 重新 RESTORE,再按正确时间点前滚 |
ROLLFORWARD CANCEL 不是暂停或正常完成命令。它会放弃当前恢复流程并使数据库或表空间进入需要重新恢复的状态,只应在确认本次恢复链不再继续时使用。
11. 所有恢复场景都应完成的检查
镜像到达目标端后:
stat /db2backup/LABDB/<目录>/LABDB*.001
sha256sum /db2backup/LABDB/<目录>/LABDB*.001
db2ckbkp -h /db2backup/LABDB/<目录>/LABDB*.001恢复和前滚期间:
db2 "rollforward db LABDB query status using local time"
db2 get db cfg for LABDB | \
egrep -i "Backup pending|Rollforward pending|Restore pending|Path to log files|Mirror log path|LOGARCHMETH1"最终开放后:
db2 connect to LABDB
db2 list history backup all for LABDB
db2 activate db LABDB
db2pd -db LABDB -logs还必须执行一组能代表真实业务一致性的查询。接管后的新主库要验证新日志链已经真正归档,并建立新的完整备份;仅看到数据库可连接,不能证明恢复闭环完成。
十九、实验中遇到的错误与判断方法
| 现象 | 原因 | 正确处理 |
|---|---|---|
db2 list active database 报 SQL0104N | 命令需要复数 databases | 使用 db2 list active databases |
LOGARCHMETH1 返回 SQL5099N reason code 2 | 归档目录不存在或路径大小写错误 | 创建目录并使用完全一致的路径 |
ARCHIVE LOG 返回 SQL1493N | CLP 仍连接着数据库 | 先 connect reset 和 terminate |
RESTORE 返回 SQL2068N no media header | 目标镜像为零字节或损坏 | 检查 stat、SHA-256 和 db2ckbkp |
ROLLFORWARD QUERY STATUS 返回 SQL1013N | 前一步恢复根本没有成功,数据库不存在 | 回到 RESTORE 错误排查 |
Rollforward pending = DATABASE | 整个数据库处于前滚暂挂 | 这是预期状态,不是异常 |
db2pd -db ... -logs 提示数据库未激活 | db2pd 只能检查活动数据库 | 先显式 activate db |
Next log file 看似没有推进 | DB working 状态可能保留当前追赶位置 | 结合 processed range 和 commit time 判断 |
| 接管后 Archive Status 短暂 Failure | 旧日志来自 overflow path,新日志链正在过渡 | 查 db2diag.log,再主动切换并归档新链日志验证 |
INCLUDE LOGS COMPRESS 报 SQL0104N | DB2 9.7 参数顺序不接受 | 使用 COMPRESS INCLUDE LOGS |
二十、生产环境如何把这套方案做稳
1. 自动化传输必须避免半文件被误用
建议采用临时文件名传输,校验成功后再原子改名。例如先传成:
S0000006.LOG.part校验大小和 SHA-256 后再改为正式文件名。前滚脚本只扫描正式的 S*.LOG,避免读取仍在传输的文件。
2. 主动归档后必须等待文件真正落稳
ARCHIVE LOG FOR DATABASE 会切换当前活动日志并触发归档,但生产脚本仍应等待归档结果:
- 检查
Method 1 Archive Status没有失败。 - 等待目标日志文件出现,并连续多次确认大小不再变化。
- 计算源端 SHA-256,再开始传输。
- 目标端重新计算 SHA-256,确认一致后再进入前滚目录。
不要按每笔事务或极短周期无节制执行 ARCHIVE LOG。频繁切换会生成大量小日志并增加活动日志管理压力,调度周期应根据日志量、RPO、网络和可用日志空间确定。
3. 监控日志链连续性
至少监控:
- 主库
Method 1 Archive Status。 Method 1 Next Log to Archive。- 备库
Log files processed。 - 备库
Last committed transaction。 - 主备最后归档日志序号差。
- 文件传输退出码、文件大小和校验结果。
- 缺失日志、损坏日志和空间不足告警。
日志序号出现缺口时不能跳过。例如已有 S0000008.LOG,但缺少 S0000007.LOG,前滚无法依靠日志 8 绕过日志 7。
4. 区分灾难恢复和延迟恢复
备库可以持续追到最新,也可以人为保留一段应用延迟:
- 追得越近,灾难切换时需要处理的尾日志越少,RTO 越短。
- 保留延迟,可以给误删除、误更新提供更长的人工干预窗口。
- 归档日志仍应持续传送,只是延迟执行前滚,不能延迟日志保护本身。
具体延迟时间必须结合 RPO、误操作风险、日志量和磁盘空间确定。
5. 定期重建备库基线
长期无限追加日志会增加管理复杂度。建议定期:
- 在主库生成新的完整备份。
- 对镜像执行
db2ckbkp。 - 在备库重新恢复并保持前滚暂挂。
- 验证最新日志可以继续应用。
- 完成一次真实演练并记录 RPO、RTO。
6. 切换必须包含 fencing
备库执行 AND STOP 后,旧主库不能继续写入。生产切换流程至少要包含:
- 停止业务应用。
- 阻断旧主库连接入口。
- 停止或隔离旧数据库。
- 确认最后日志已经归档和传送。
- 提升备库并验证。
- 更新 VIP、DNS、连接串或负载均衡入口。
如果旧主库和新主库同时接受写入,就会形成 split-brain。普通备份与日志前滚无法自动合并两边的独立事务。
7. 接管后不要忘记重新建立保护链
接管完成后应立即:
- 验证新日志链归档成功。
- 执行新的完整在线备份并包含日志。
- 重新规划从新主库到新备库的日志传送方向。
- 保留旧备份和旧日志,直到新备份完成验证并满足保留策略。
- 将原主库清理并重建为新的备库,而不是直接重新开放。
二十一、总结
这次实验最重要的结论不是“DB2 可以恢复备份”,而是验证了完整的恢复链:
- 离线全备可以恢复出明确的备份时刻快照。
- 启用归档日志后,可以用新全备建立备库基线。
- RESTORE 时省略
WITHOUT ROLLING FORWARD,即可使备库保持前滚暂挂。 TO END OF LOGS不加STOP可以反复应用最新归档日志。- 切换前预同步能把最终停机窗口压缩到尾日志传送和
AND STOP。 - 本次已提交事务全部恢复,RPO 为 0;DB2 最终尾日志处理只用了 0.504 秒。
- 真正的端到端 RTO 更多取决于自动化、网络、校验、决策和业务切换,而不是最后一条 DB2 命令。
- 接管后的归档日志、新日志链和完整备份必须继续验证,否则只能算“暂时能查数据”,不能算恢复体系闭环。
对于没有部署 HADR、但需要用较低成本控制 RPO 和 RTO 的 DB2 环境,这种“完整备份 + 归档日志持续传送 + 备库持续前滚”的方式具备实际可操作性。它的可靠性最终取决于日志链是否连续、传输是否可验证、切换是否有 fencing,以及演练是否真正执行过。