归档:把刷盘线程里的 RLOG_PKG 送到本机目录,或经 MAL 送到另一个实例。归档一共九类。本文只写 本地(LOCAL)、实时(REALTIME)、即时(TIMELY),以及实时路径上的 KEEP_RLOG_PKG。其余(REMOTE、ASYNC、SYNC、SUBSCRIBE、RAFT、LEARNER)不展开。
实时、即时只在 PRIMARY 上真正发送。目标实例必须是 STANDBY。DM 实时目标 1~8 个,即时目标 1~8 个。任意一路实时或即时失败,主库进 SUSPEND。发送方是日志刷盘线程,不是 dmwatcher。
配置文件是实例目录下的 dmarch.ini,dm.ini 里 ARCH_INI=1 才会读它。同一 GLOBAL 守护组内,各实例的 ARCH_TYPE 集合要配成一样。
NORMAL / PRIMARY:包写入联机日志之后,归档线程再写本地文件。STANDBY:收到对端原包后直接写入本地归档,同时 APPLY;本机重演时新写的 Redo 只进联机日志,不进归档文件。于是组内各节点归档文件里都是「源库产生的那份包」,不是各写各的联机日志拷贝。
联机日志两个文件循环覆盖。本地归档不能覆盖,直到删除或碰到空间上限。ARCH_SPACE_LIMIT=0 表示不限制;盘满且所有本地归档的 ARCH_HANG_FLAG 行为又要求挂起时,实例停在那里等空间。
| 字段 | 含义 |
|---|---|
| PMNT_MAGIC | 库初始化时生成,组内相同(DDL_CLONE 还原并 UPDATE DB_MAGIC 除外) |
| DB_MAGIC | 标识写入这份归档文件的库。初始化生成,还原后会变。组内各库不同 |
| SRC_DB_MAGIC | 标识产生 Redo 的库。主库归档里与 DB_MAGIC 相同;备库归档里等于主库 DB_MAGIC |
PRIMARY/NORMAL 文件名:
ARCH_NAME_DB_MAGIC_EP节点号_YYYY-MM-DD_HH-MM-SS.log
例:ARCHIVE_LOCAL1_0x567891_EP0_2022-03-20_10-35-34.log
STANDBY 文件名:
STANDBY_ARCHIVE_P_DB_MAGIC_EP节点号_SELF_DB_MAGIC_日期时间.log
例:STANDBY_ARCHIVE_0x123456_EP0_0x234567_2022-03-20_10-35-34.log
节名不要叫 STANDBY_ARCHIVE,手册保留给备库生成的文件。
完整本地段:
ARCH_WAIT_APPLY = 0
ARCH_RESERVE_TIME = 0
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dmarch/DAMENG/
ARCH_FILE_SIZE = 1024
ARCH_SPACE_LIMIT = 5120
ARCH_FLUSH_BUF_SIZE = 2
ARCH_HANG_FLAG = 1
| 项 | 范围与默认 | 说明 |
|---|---|---|
| ARCH_FILE_SIZE | 64~2048 MB,默认 1024 | 单个归档文件,仅 LOCAL |
| ARCH_SPACE_LIMIT | 0 或 1024~2147483647 MB,默认 0 | 0 不限制;到上限删最早的文件 |
| ARCH_FLUSH_BUF_SIZE | 0~128 MB,默认 2 | 0 关闭归档刷盘缓存 |
| ARCH_HANG_FLAG | 0/1/2,默认 1 | 见下 |
| ARCH_RESERVE_TIME | 分钟,默认 0 | 仅 LOCAL。0 不按时间删。服务器约每 5 分钟扫一次超龄文件 |
ARCH_HANG_FLAG:
0:写失败直接报错,不再试。1:挂起,反复写直到成功。2:删最老文件再写,删光仍失败则报错返回。若库上所有本地归档都不是 1,写失败可能造成归档缺口,后面备份还原会缺日志。
删归档(单机本地归档也可以用;有备库时不要删对方还没拿到的那段):
SELECT SF_ARCHIVELOG_DELETE_BEFORE_TIME('2026-01-01 00:00:00');
SELECT SF_ARCHIVELOG_DELETE_BEFORE_LSN(100000);
第二个参数换成现场 V$RLOG 里已经不需要的 LSN,不要拍脑袋填。
时机:写入主库联机日志 之前,MAL 把包发给目标。目标 CTL 校验连续性、是否 OPEN。失败则主库试图 SUSPEND;磁盘损坏一类会 HALT。成功:旧 KEEP 进 APPLY 队列,新包留在内存当 KEEP,然后响应。默认不等 APPLY 完。主库收齐全部实时目标的成功响应,才写自己的联机日志,再走本地归档。
失败时该路状态先不改 Invalid,交给守护 Failover。即时失败则立刻 Invalid。
[ARCHIVE_REALTIME1]
ARCH_TYPE = REALTIME
ARCH_DEST = STANDBY_INST_NAME
WAIT_APPLY = 0
ARCH_FAILOVER = 0
ARCH_DEST 是目标 实例名,与 INSTANCE_NAME 一致,不能写本实例、不能写 IP。目标若是 DSC,写成 DSC01/DSC02 这种用 / 拼起来的全部实例名。
ARCH_SEND_POLICY(全局,仅 REALTIME):
0(默认):发出去就等响应,再写联机日志。1:先写联机日志,同时等响应,刷盘和等待重叠。ARCH_FAILOVER 仅 REALTIME/TIMELY,且仅 DW_TYPE=GLOBAL 且 DW_MODE=AUTO 时有意义。0:发送失败要 SUSPEND,走守护 Failover,该目标允许自动接管。1:该目标不允许自动接管,仍可手动接管。默认 0。
ARCH_STANDBY_APPLY:是否按目标已重演 LSN 决定本机本地归档能不能删。0 否(默认),1 是。多个目标都配了,按已重演 LSN 最小的那路来。支持 REALTIME/TIMELY/SYNC/ASYNC/RAFT。
实时路径上,目标确认「收到」时,源端联机日志里可能还没有这一包。若目标立刻重演,源端在落盘前宕机:源端重启后包不在自己的联机日志里,目标页上已经有。只能切角色,再把旧源端重建。
因此目标把 最新一包 放在内存,不立刻重演,称为 KEEP_RLOG_PKG。KLSN / KSEQ 描述这包。即时路径先落盘再发,不会出现「目标比源端联机日志多一包」,没有 KEEP。
KEEP 重演的三个时机:
源端仍以 PRIMARY 起来时,守护可以让目标丢掉 KEEP,不必切一次角色。
视图在跑实时目标的实例上:
SELECT * FROM V$KEEP_RLOG_PKG;
SELECT * FROM V$RAPPLY_SYS;
SELECT * FROM V$RAPPLY_LOG_TASK;
SELECT * FROM V$RAPPLY_PARALLEL_INFO;
空闲时 KEEP 非空是常见现象:最新一包还在等落盘确认或等下一包。
时机:先写入源端联机日志(并本地归档),再 MAL 发送。目标校验后直接 APPLY。
失败:该路立刻 Invalid,源端 SUSPEND。该目标上若有影子会话,会被断开。
即时的组分裂窗口:源端已落盘、尚未发出去时宕机,目标少一包。强制接管后旧源端再起来,可能判分裂,要备份还原。KEEP 管的是相反的窗口(目标多一包)。
[ARCHIVE_TIMELY1]
ARCH_TYPE = TIMELY
ARCH_DEST = STANDBY_INST_NAME
WAIT_APPLY = 1
ARCH_FAILOVER = 0
| LOCAL | REALTIME | TIMELY | |
|---|---|---|---|
| 目标个数 | 最多 8 | 1~8 | 1~8 |
| 走 MAL | 否 | 是 | 是 |
| 时机 | 写入联机日志后写文件 | 写入联机日志前发送 | 写入联机日志后发送 |
| 谁做 | 归档线程 | 刷盘线程 | 刷盘线程 |
| 失败 | 盘满按 HANG_FLAG;盘坏 HALT | SUSPEND,状态先不动,等守护 | SUSPEND,该路立刻 Invalid |
| 目标响应 | 无 | 见 WAIT_APPLY | 见 WAIT_APPLY |
| 源模式 | PRIMARY / STANDBY / NORMAL | PRIMARY | PRIMARY |
| 目标模式 | 无 | STANDBY | STANDBY |
归档状态:LOCAL / REALTIME / TIMELY 为 Valid、Invalid。Valid 正常干活。Invalid:源端不再把联机包发到该目标。启动时默认 Valid;守护 Open 主库前,日志对不齐的路会改成 Invalid。实时失败挂起后 Failover 再改 Invalid。即时失败直接 Invalid。恢复追上后:源端 SUSPEND → 该路改 Valid → 再 OPEN。
SELECT ARCH_NAME, ARCH_TYPE, ARCH_DEST, ARCH_STATUS
FROM V$DM_ARCH_INI;
SELECT * FROM V$ARCH_STATUS;
MOUNT 下才能改归档配置(不含增加/删除同步归档这类例外)。PRIMARY 下还有「不能改 arch_ini 参数」等限制,改 dmarch.ini 后通常要 MOUNT 再生效。
仅 REALTIME、TIMELY。文件头全局项 ARCH_WAIT_APPLY;某段上写了 WAIT_APPLY 则以该段为准。
| 值 | 名称 | 行为 |
|---|---|---|
| 0 | 高性能 | 收到即响应,再 APPLY。实时默认 |
| 1 | 事务一致 | APPLY 完再响应。即时默认 |
事务一致:COMMIT 返回时该包已在目标侧重演完。之后按读提交查已提交数据,在源端和目标端应对齐。尚未返回时两边都看不到这次更新。目标越多,提交越慢。
高性能:COMMIT 可在 APPLY 前返回。下一句若在目标端查询,可能仍是上一时刻。
-- 高性能下会踩空的写法(逻辑上,不必真有第二实例)
INSERT INTO T VALUES (1);
COMMIT;
-- 紧接着若在尚未 APPLY 的副本上:
SELECT TOP 1 C1 INTO VAR1 FROM T;
UPDATE T SET C1 = VAR1 + 1 WHERE C1 = VAR1;
实时路径上 WAIT_APPLY=1 还要求守护 AUTO。DSC 作实时守护源时不能把该项配 1。
看 ARCH_INI、归档线程、文件滚动、空间上限、按 LSN 删除。
数据在 /dmdata/DAMENG,归档在 /dmarch/DAMENG。
mkdir -p /dmarch/DAMENG
dm.ini 里确认或准备设:
ARCH_INI = 1
若库已在跑,MOUNT 后改:
ALTER DATABASE MOUNT;
SP_SET_PARA_VALUE(2, 'ARCH_INI', 1);
dmarch.ini 只保留本地段,路径存在且对启动用户可写:
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dmarch/DAMENG/
ARCH_FILE_SIZE = 64
ARCH_SPACE_LIMIT = 1024
ARCH_HANG_FLAG = 1
ARCH_FLUSH_BUF_SIZE = 2
把 ARCH_FILE_SIZE 临时改小,容易看到第二个文件出现。改完 OPEN:
ALTER DATABASE OPEN;
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'ARCH_INI';
SELECT ARCH_NAME, ARCH_TYPE, ARCH_DEST, ARCH_STATUS FROM V$DM_ARCH_INI;
SELECT CUR_LSN, FILE_LSN, CKPT_LSN FROM V$RLOG;
造 Redo(单机会写联机日志,本地归档应跟上):
CREATE TABLE ARCH_SOLO(C1 INT, C2 VARCHAR(100));
BEGIN
FOR I IN 1..20000 LOOP
INSERT INTO ARCH_SOLO VALUES (I, 'redo-gen');
IF MOD(I, 1000) = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT;
END;
/
CHECKPOINT;
SELECT CUR_LSN, FILE_LSN, CKPT_LSN FROM V$RLOG;
看目录(Linux):
ls -l /dmarch/DAMENG/
ls /dmarch/DAMENG/*.log | wc -l
du -sh /dmarch/DAMENG
应出现 ARCHIVE_LOCAL1_<DB_MAGIC>_EP0_*.log。文件个数随 ARCH_FILE_SIZE 和日志量增加。到 ARCH_SPACE_LIMIT 后最早的文件会被删。
查魔数,核对文件名里的那一截:
SELECT DB_MAGIC FROM V$DATABASE;
-- 若当前版本无此列,用:
SELECT * FROM V$DATABASE;
再把 ARCH_SOLO 多插几轮,对比 FILE_LSN 前进和目录里最新文件的时间戳。
按 LSN 删之前先记下当前 FILE_LSN,只删明显落后的值:
SELECT FILE_LSN, CKPT_LSN FROM V$RLOG;
-- 确认该 LSN 已不需要保留后再执行,例如:
-- SELECT SF_ARCHIVELOG_DELETE_BEFORE_LSN(某个已过时的值);
删完再 ls,最早的文件应减少。ARCH_RESERVE_TIME 配成较小分钟数后等两个 5 分钟周期,也可看到超龄文件消失。
挂起策略不要在生产盘上用 0 做实验。单机若故意把 ARCH_DEST 指到只读目录,ARCH_HANG_FLAG=1 时会话会卡在归档写入;改回可写目录或把 flag 改掉并重启归档配置后才能恢复。做这种试验用独立目录。
相关状态(单机也能执行,和归档失败时的主库行为是同一组语句):
ALTER DATABASE SUSPEND;
ALTER DATABASE OPEN;
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;
SUSPEND 限制 Redo 刷盘,COMMIT 会卡住。看清效果后立刻 OPEN,不要挂在业务库上。PRIMARY/STANDBY 下 OPEN 要加 FORCE。单机 NORMAL 一般不用 FORCE。
ALTER DATABASE PRIMARY / STANDBY 会改角色。没有第二实例时不要改成 STANDBY 。
相关上机截图:



即时:源端已把包写入联机日志,MAL 尚未送到目标时源端宕机。目标少包。强制接管后旧源端再起,组分裂。
实时:KEEP 填的是目标多包、源端未落盘。升主前重演 KEEP;源端继续当主则丢 KEEP。
两种窗口都不是守护「重做日志」能凭空补出来的。分裂库看 dmwatcher.ctl,重建靠备份还原。
文章
阅读量
获赞
