注册
从 DDIA 看 DM8 的 MAGIC NUMBER:数据库为什么需要两个身份
专栏/技术分享/ 文章详情 /

从 DDIA 看 DM8 的 MAGIC NUMBER:数据库为什么需要两个身份

FoxZzz 2026/09/30 211 0 0
摘要

在 DM8 的备份恢复和数据守护中,经常会遇到两个参数:PERMANENT_MAGIC 和 DB_MAGIC。尤其是在执行数据库恢复时,我们通常会看到最后一步:

RECOVER DATABASE '/dmdata/DAMENG/dm.ini' UPDATE DB_MAGIC;
  • 为什么数据库已经完成还原和 REDO 恢复,还需要单独更新一次 DB_MAGIC?
  • 为什么搭建数据守护时,官方要求通过备份还原准备备库,而不能简单地分别初始化两个数据库?

如果只把 MAGIC 理解成一个“随机编号”,这些操作很难真正理解。按照达梦官方文档,PERMANENT_MAGIC 和 DB_MAGIC 都是在初始化数据库时生成、用于标识数据库的整数值。其中 PERMANENT_MAGIC 生成后通常不会改变,只有 DDL_CLONE 等特殊场景例外;DB_MAGIC 则会在数据库经过还原、恢复之后发生变化,用于区分备份源库和还原目标库。官方还明确将数据库恢复划分为“恢复一致性”和“更新 DB_MAGIC”两个步骤。

一、PERMANENT_MAGIC:解决“是不是同一个来源”的问题

理解 MAGIC,可以先从 PERMANENT_MAGIC 开始。达梦官方数据守护文档明确指出,每个数据库都有永久魔数,主库进行日志传输时会判断该值是否一致,以确认数据库来自同一个数据守护环境;如果永久魔数不一致,日志无法正常传输。因此,数据守护搭建前必须通过备份还原方式同步数据,官方明确不允许通过“分别初始化两个数据库”的方式直接组成数据守护。
这个设计可以借用 DDIA 的思想来理解。分布式系统中,一个节点“在哪里”和它“是谁”并不是同一件事。IP 地址、主机名、端口甚至实例名都可以被重新使用。比如一台服务器重新安装后,仍然可以使用原来的 IP 和实例名,但服务器上的数据库实际上已经重新初始化。如果只依赖这些外部属性,就无法可靠判断两个数据库之间是否存在共同的数据来源。
因此,可以把 PERMANENT_MAGIC 理解为数据库的一种来源身份:

PERMANENT_MAGIC ——> 这些数据库是否来源于同一个数据库体系?

这里为了便于理解,可以借用 lineage,也就是“数据血统”这个概念。需要强调的是,lineage 是本文用于解释设计思想的概念,并不是达梦官方对 PERMANENT_MAGIC 的正式命名。
如果主库的备份被用于恢复一个备库,恢复后的数据库继承了原数据库的永久 MAGIC,因此二者可以被识别为来自同一个数据守护体系。反过来,如果两边分别运行 dminit,就会生成各自的永久 MAGIC。即使两边的表结构、用户名甚至业务数据看起来完全相同,从数据库内部身份来看,它们仍然不是同一个来源。
从 DDIA 的角度,可以把这个关系概括成一句话:

Identity 不应该依赖 Location。

数据库运行在哪里,与数据库本身的身份是两个不同的问题。

二、DB_MAGIC:同一个来源,还要继续区分“你到底是谁”

有了 PERMANENT_MAGIC,为什么还需要一个 DB_MAGIC?
这是 MAGIC 设计中最关键的问题。
假设有一个数据库 A,我们在某个时间点对它进行了备份。备份完成之后,数据库 A 继续运行,持续产生新的事务和 REDO。随后,我们使用之前的备份恢复出了数据库 B。
此时 A 和 B 显然存在共同来源,因为 B 的数据来自 A 的备份。但从恢复完成的那一刻开始,它们已经成为两个可以独立运行的数据库。
也就是说:

		同一个源数据库
                     │
                   BACKUP
                     │
             ┌───────┴───────┐
             │               │
             ▼               ▼
         原数据库 A       恢复数据库 B

如果系统只有 PERMANENT_MAGIC,那么它只能表达:A 和 B 来自同一个数据库来源,却无法进一步表达:A 和 B 已经是两个不同的数据库,所以还需要引入 DB_MAGIC 。
达梦官方文档明确说明,DB_MAGIC 同样可以用于标识某一个数据库,但与永久 MAGIC 不同,它可以发生变化;数据库每经过一次还原、恢复后,DB_MAGIC 会发生变化,以此区分备份源库与还原目标库。
如果借用分布式系统里的概念,可以把它理解成一种 Database Incarnation Identity,即数据库某一次具体存在形态的身份:

PERMANENT_MAGIC ——> 我们是不是来自同一个数据库来源?
DB_MAGIC ——> 即使来源相同,我具体是哪一个数据库?

这里的 Incarnation 同样是用于帮助理解的分析概念,而不是达梦官方术语。
因此,当 PERMANENT_MAGIC 相同而 DB_MAGIC 不同时表达的是

来自同一个数据库来源,但现在是两个不同的数据库。
这也解释了为什么 DM 需要两个 MAGIC,而不是只设计一个数据库 ID。

三、为什么数据库恢复完成后还要 UPDATE DB_MAGIC

理解了前面的身份模型,UPDATE DB_MAGIC 就很好解释了。
达梦官方将数据库恢复明确划分为两个阶段:

  • 第一步:恢复一致性
  • 第二步:更新 DB_MAGIC

其中,第一步主要通过重做 REDO 等方式,使目标数据库达到一个一致的数据状态;第二步则更新目标数据库的 DB_MAGIC,并将数据库调整为可正常工作的状态。官方同时说明,数据库还原之后,更新 DB_MAGIC 是数据库级还原需要执行的步骤,而表空间等其他类型的还原不需要执行。
典型流程就是:

RESTORE DATABASE
        │
        ▼
恢复数据文件
        │
        ▼
RECOVER DATABASE
        │
        ▼
利用 REDO 恢复一致性
        │
        ▼
RECOVER DATABASE UPDATE DB_MAGIC
        │
        ▼
生成新的数据库身份

这里可以看出两个完全不同的问题。

  • RECOVER DATABASE 主要解决:数据现在是否一致?
  • RECOVER DATABASE … UPDATE DB_MAGIC 进一步解决: 恢复完成后,这个数据库以什么身份存在

因此,从 DDIA 的视角,可以把这两个阶段分别理解为:

  • Recovery ——> 恢复数据库历史和数据状态
  • Identity transition ——> 区分恢复后的数据库和原备份源数据库

所以 UPDATE DB_MAGIC 不是简单地“为了让数据库能启动随便改一个数字”,它有非常明确的身份区分作用。

四、到了数据守护和归档日志中,MAGIC 的意义更加明显

MAGIC 不仅存在于数据库自身,也进入了 DM 的日志体系。
达梦官方的 V$ARCH_FILE 动态视图中,可以看到:DB_MAGIC,PMNT_MAGIC,SRC_DB_MAGIC

参数 含义
DB_MAGIC 写入日志的数据库 MAGIC
PMNT_MAGIC 数据库永久 MAGIC
SRC_DB_MAGIC 产生日志的源数据库 MAGIC

同时,视图中还记录 ARCH_LSN、CLSN、PREV_LSN 等日志位置信息。
数据守护文档进一步说明:DB_MAGIC 在数据库初始化时生成,数据库还原后会重新生成新的 DB_MAGIC;数据守护中的主备数据库具有不同的 DB_MAGIC。对于归档日志,主库归档中的 SRC_DB_MAGIC 与自身 DB_MAGIC 相同;备库生成的归档中,SRC_DB_MAGIC 则记录产生 REDO 的源数据库,也就是主库的 DB_MAGIC。
这说明 DM 在记录一份日志时,可以提供以下信息:

  • 这份日志的 LSN 是多少?
  • 这份日志属于哪个数据库?
  • 是谁产生了这份 REDO?
  • 又是谁写下了这份归档?

这时候,用 DDIA 的方法重新拆解就会非常清晰:

参数 含义
PERMANENT_MAGIC 数据库来源关系
DB_MAGIC 具体数据库身份
SRC_DB_MAGIC REDO 来源身份
LSN 日志历史中的位置

换句话说,MAGIC 和 LSN 解决的不是同一个问题。
MAGIC 更接近回答:Who?这是谁的数据、谁的日志?
而 LSN 更接近回答:Where in history?这份日志处在数据历史的什么位置?
因此,仅仅看到两个数据库的 LSN 一样,并不能从逻辑上把“LSN 相等”直接等价成“两个数据库身份相同”。身份与日志位置本来就是不同维度。

五、从 DDIA 重新理解 DM MAGIC 的设计

如果把达梦官方明确描述的这些机制放在一起,再借用 DDIA 的分布式系统思维,可以得到一个比较清晰的模型:

		DM Database
                     │
     ┌───────────────┼───────────────┐
     │               │               │
     ▼               ▼               ▼
  来源关系          数据库身份        日志历史
     │               │               │
     ▼               ▼               ▼
PERMANENT_MAGIC    DB_MAGIC        LSN / REDO

如果进一步放到数据守护系统中,还需要加上:

PRIMARY / STANDBY
Watcher
Monitor
故障切换

这一层解决的是另外一个问题:

谁当前应该承担 PRIMARY 角色?

达梦官方文档明确说明,数据守护依靠主备 Redo 传输与重演保持同步,守护进程负责监控数据库运行状态和同步状态,监视器用于监控系统、执行命令以及实现自动切换等功能。
所以不能把 DB_MAGIC 理解成“谁的值大谁就是主库”,也不能把它简单等同于 Raft 的 Term、Leader Epoch 或严格意义上的 fencing token。达梦官方对 DB_MAGIC 给出的核心语义,是标识数据库,并区分备份源库和还原目标库;主备切换和故障处理属于数据守护的另一套机制。
如果用四句话概括,就是:

PERMANENT_MAGIC
        ↓
我们是不是来自同一个数据库来源?

DB_MAGIC
        ↓
在共同来源下,我具体是哪一个数据库?

LSN / REDO
        ↓
我的数据历史推进到了什么位置?

PRIMARY / STANDBY / Data Watch
        ↓
当前数据库承担什么角色?

这几个维度有关联,但不能互相替代。

六、总结

第一次看到 PERMANENT_MAGIC 和 DB_MAGIC,很容易觉得 DM 只是给数据库保存了两个不同的编号。
但从备份恢复和数据守护的完整流程来看,它实际上解决的是两个不同层次的身份问题。
PERMANENT_MAGIC 保留下来的,是数据库之间的来源关系。数据守护在日志传输过程中会检查永久 MAGIC,以确认数据库属于同一个数据守护环境。
DB_MAGIC 解决的则是另一个问题:即使两个数据库来自同一个来源,在经过备份、还原和恢复以后,它们也需要成为可以相互区分的数据库。于是恢复流程最终通过:

RECOVER DATABASE '<dm.ini>' UPDATE DB_MAGIC;

更新目标数据库的 MAGIC。
所以,如果借用 DDIA 的方法,而不是把这些概念机械地对应,可以把 DM 的 MAGIC 设计理解成:

PERMANENT_MAGIC → 来源 / Lineage

DB_MAGIC        → 身份 / Incarnation

LSN + REDO      → 历史 / Ordering

其中前两个概念是对 DM 官方机制的抽象解释,Lineage 和 Incarnation 并不是达梦官方术语。
最终可以用一句话概括:

PERMANENT_MAGIC 用来判断数据库是不是“同源”,DB_MAGIC 用来判断同源数据库中“具体是谁”。数据可以从备份中继承,但恢复出来的数据库必须拥有能够区分自己的身份。
理解这一点之后,再去看 DM 为什么要求通过备份还原搭建数据守护、为什么恢复最后必须执行 UPDATE DB_MAGIC、为什么归档日志还要保存 DB_MAGIC 和 SRC_DB_MAGIC,这些看起来零散的机制实际上都指向了同一个核心问题——数据库身份必须能够被可靠地识别。

七、参考资料

  • 《DM8 备份与还原》——备份还原原理、数据库恢复及 DB_MAGIC
  • 《DM8 数据守护与读写分离集群》——数据守护搭建、MAGIC 校验及主备数据准备
  • 《DM8 系统管理员手册》——V$ARCH_FILE 动态性能视图
  • 《DM8 数据守护与读写分离集群》概述——Redo 传输、日志重演、DB_MAGIC 与 SRC_DB_MAGIC
  • 《DDIA 数据密集型应用系统设计》—— 分布式系统中 Identity、Lineage、Incarnation、History 的概念
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服