HOME

【DB2 数据库】12 备份恢复实战:离线全备、持续前滚与最小停机接管

文章目录62 节

一、这篇文章要验证什么

这次实验不是只执行一次 BACKUPRESTORE,而是围绕两类核心恢复目标,记录四个实测阶段,并补充常见备份恢复场景和参数边界:

  1. 使用离线全备恢复出备份时刻的一致性快照。
  2. 把全备恢复到另一台服务器,长期保持 ROLLFORWARD PENDING,多轮应用主库最新归档日志,但不立即执行 STOP
  3. 切换前先让备库追到接近主库的位置,只在最终停写后传送一小段尾日志。
  4. 在备库执行 AND STOP,验证最终数据、RPO、RTO、新日志链以及接管后备份。

第二种方式本质上是一套基于备份与归档日志传送的暖备方案。它不是 DB2 HADR,也不是双活;备库在接管前不能提供普通 SQL 访问,但可以持续缩短与主库之间的日志差距。

实验过程中还保留了真实遇到的错误,包括路径大小写、零字节备份、DB2 9.7 参数顺序、前滚状态误读和接管后的归档状态检查。

二、脱敏后的实验环境

本文中的主机名、地址、数据库名和路径均已替换为实验示例。正式操作时必须按实际环境修改。

项目主库备库
主机名db-primarydb-standby
示例地址192.0.2.10192.0.2.20
操作系统SLES 12 SP5SLES 12 SP5
DB29.7 FP6 64 位9.7 FP6 64 位
实例用户db2inst1db2inst1
数据库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 directory

DB2 支持通过 INTO 恢复成其他名称,也支持在明确授权后用 REPLACE EXISTING 覆盖已有目标,但后者具有破坏性。如果备库已经存在同名数据库,必须先确认它是否可以删除或覆盖,不能直接处理生产或测试数据。

2. 克隆服务器不能只修改主机名和 IP

如果备机由主机克隆得到,还要检查:

db2set -all
cat ~/sqllib/db2nodes.cfg

单分区实例的 DB2SYSTEMdb2nodes.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 LOGSEXCLUDE 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 CONTAINERSRESTORE ... 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 LABDB
db2 "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 - successful

3. 制造备份后的变化

db2 connect to LABDB
db2 "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 LOGDEACTIVATE 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' |
sort

DB2 会自动生成类似目录:

/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 阻止。

十二、为什么持续前滚能缩短最终恢复时间

如果备库只恢复一次全备,却长期不应用日志,故障时需要一次性处理大量归档日志,恢复时间不可控。

持续前滚的思路是:

  1. 主库正常运行并持续归档日志。
  2. 归档日志按固定周期传送到备库。
  3. 备库反复执行 TO END OF LOGS,但不执行 STOP
  4. 切换前再做一次预同步,让备库追到最近的完整日志。
  5. 正式停写后只传送最后一小段尾日志。

本次实验每次前滚约为 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 秒每轮只处理少量新日志
最终尾日志前滚并 STOP0.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 = Failure

db2diag.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 和对象所有者。
  • LOGARCHMETH1MIRRORLOGPATH 和外部归档目标。
  • 外部表、用户自定义函数、存储过程库、裸设备和应用连接配置。

如果源镜像是在线备份,应去掉 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 ... REDIRECTSET TABLESPACE CONTAINERSRESTORE ... 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 databaseSQL0104N命令需要复数 databases使用 db2 list active databases
LOGARCHMETH1 返回 SQL5099N reason code 2归档目录不存在或路径大小写错误创建目录并使用完全一致的路径
ARCHIVE LOG 返回 SQL1493NCLP 仍连接着数据库connect resetterminate
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 COMPRESSSQL0104NDB2 9.7 参数顺序不接受使用 COMPRESS INCLUDE LOGS

二十、生产环境如何把这套方案做稳

1. 自动化传输必须避免半文件被误用

建议采用临时文件名传输,校验成功后再原子改名。例如先传成:

S0000006.LOG.part

校验大小和 SHA-256 后再改为正式文件名。前滚脚本只扫描正式的 S*.LOG,避免读取仍在传输的文件。

2. 主动归档后必须等待文件真正落稳

ARCHIVE LOG FOR DATABASE 会切换当前活动日志并触发归档,但生产脚本仍应等待归档结果:

  1. 检查 Method 1 Archive Status 没有失败。
  2. 等待目标日志文件出现,并连续多次确认大小不再变化。
  3. 计算源端 SHA-256,再开始传输。
  4. 目标端重新计算 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. 定期重建备库基线

长期无限追加日志会增加管理复杂度。建议定期:

  1. 在主库生成新的完整备份。
  2. 对镜像执行 db2ckbkp
  3. 在备库重新恢复并保持前滚暂挂。
  4. 验证最新日志可以继续应用。
  5. 完成一次真实演练并记录 RPO、RTO。

6. 切换必须包含 fencing

备库执行 AND STOP 后,旧主库不能继续写入。生产切换流程至少要包含:

  • 停止业务应用。
  • 阻断旧主库连接入口。
  • 停止或隔离旧数据库。
  • 确认最后日志已经归档和传送。
  • 提升备库并验证。
  • 更新 VIP、DNS、连接串或负载均衡入口。

如果旧主库和新主库同时接受写入,就会形成 split-brain。普通备份与日志前滚无法自动合并两边的独立事务。

7. 接管后不要忘记重新建立保护链

接管完成后应立即:

  • 验证新日志链归档成功。
  • 执行新的完整在线备份并包含日志。
  • 重新规划从新主库到新备库的日志传送方向。
  • 保留旧备份和旧日志,直到新备份完成验证并满足保留策略。
  • 将原主库清理并重建为新的备库,而不是直接重新开放。

二十一、总结

这次实验最重要的结论不是“DB2 可以恢复备份”,而是验证了完整的恢复链:

  1. 离线全备可以恢复出明确的备份时刻快照。
  2. 启用归档日志后,可以用新全备建立备库基线。
  3. RESTORE 时省略 WITHOUT ROLLING FORWARD,即可使备库保持前滚暂挂。
  4. TO END OF LOGS 不加 STOP 可以反复应用最新归档日志。
  5. 切换前预同步能把最终停机窗口压缩到尾日志传送和 AND STOP
  6. 本次已提交事务全部恢复,RPO 为 0;DB2 最终尾日志处理只用了 0.504 秒。
  7. 真正的端到端 RTO 更多取决于自动化、网络、校验、决策和业务切换,而不是最后一条 DB2 命令。
  8. 接管后的归档日志、新日志链和完整备份必须继续验证,否则只能算“暂时能查数据”,不能算恢复体系闭环。

对于没有部署 HADR、但需要用较低成本控制 RPO 和 RTO 的 DB2 环境,这种“完整备份 + 归档日志持续传送 + 备库持续前滚”的方式具备实际可操作性。它的可靠性最终取决于日志链是否连续、传输是否可验证、切换是否有 fencing,以及演练是否真正执行过。

Linux DB2 数据库 备份恢复 灾难恢复