注册
DBMS_LOGMNR挖掘分析归档日志
技术分享/ 文章详情 /

DBMS_LOGMNR挖掘分析归档日志

早睡早起- 2026/04/30 446 1 0

1 挖掘分析归档的目的

在数据库的日常运维中,难免会因误操作导致数据丢失。如果数据库没有配置闪回或审计功能,直接采用“备份+归档”的方式虽然能恢复数据,但往往耗时较长,且可能影响业务连续性。此时,我们可以通过挖掘和分析归档日志,快速定位误操作记录,追溯执行该操作的具体业务用户及其来源IP地址,为精准恢复丢失数据和责任追溯提供关键依据。

通过DBMS_LOGMNR挖掘分析达梦数据库的归档日志,核心作用在于实现数据变更的精准追溯与审计。它能够完整还原数据库的历史操作记录,包括DML(增删改)和DDL(表结构变更)语句,帮助DBA快速定位数据误操作、排查业务逻辑错误,并为数据恢复提供关键依据,是保障数据安全与合规性的重要工具。

使用DBMS_LOGMNR对归档日志进行挖掘分析时会造成一定的资源消耗,为避免影响业务系统的正常运行,建议将归档日志拷贝至测试环境进行操作。

2 测试场景

本测试场景旨在验证通过DBMS_LOGMNR挖掘分析归档日志后恢复误删数据的可行性:在开启归档及附加逻辑日志参数的前提下,由用户USER01创建业务表并插入测试数据,随后将该表权限授予USER02;通过USER02用户模拟执行 UPDATE和DELETE误操作,造成数据异常丢失;最终利用DBMS_LOGMNR工具对归档日志进行挖掘分析,验证是否能成功捕获误操作事务,从而实现数据的精准恢复。

3 测试过程

3.1 源库环境准备

若需要使用DBMS_LOGMNR挖掘分析源库的归档日志,源库必须开启附加逻辑日志参数,开启后所产生的归档日志才可以进行挖掘分析。

--查询归档是否开启 SELECT ARCH_MODE FROM V$DATABASE; --开启归档日志 alter database mount; alter database archivelog; alter database add archivelog 'DEST=/dmarch, TYPE=LOCAL, FILE_SIZE=256, SPACE_LIMIT=2048'; alter database open; --查询附件逻辑日志是否开启 SELECT * FROM V$DM_INI WHERE PARA_NAME = 'RLOG_APPEND_LOGIC'; --开启附加逻辑日志 SP_SET_PARA_VALUE(1,'RLOG_APPEND_LOGIC',1); --RLOG_APPEND_LOGIC参数取值范围及说明 0:不启用;1、2、3、4 启用。 1:如果有主键列,记录 UPDATEDELETE 操作时只包含主键列信息,若没有主键列则包含所有列信息; 2:不论是否有主键列,记录 UPDATEDELETE 操作时都包含所有列的信息; 3:记录 UPDATE 时包含更新列的信息以及 ROWID,记录 DELETE 时只有 ROWID4:只生成事务以及 DDL 相关的逻辑日志 注:DELETE 和 UDPATE 操作日志中描述的“所有列的信息”不包含大字段列(如 BLOBCLOB 类型的列)

3.2 源库模拟误操作

  • 创建测试用户USER01和USER02
CREATE TABLESPACE "TBS_USER" DATAFILE 'TBS_USER01.DBF' SIZE 128 AUTOEXTEND ON NEXT 2048; CREATE USER "USER01" IDENTIFIED BY "Dameng@1234" DEFAULT TABLESPACE "TBS_USER"; GRANT "PUBLIC","RESOURCE","VTI","SOI","SVI" TO "USER01"; CREATE USER "USER02" IDENTIFIED BY "Dameng@1234" DEFAULT TABLESPACE "TBS_USER"; GRANT "PUBLIC","RESOURCE","VTI","SOI","SVI" TO "USER02";
  • USER01创建表并插入测试数据
--测试数据 CREATE TABLE USER01.TEST_01(C1 INT,C2 VARCHAR(20)); INSERT INTO USER01.TEST_01 VALUES(1,'测试数据001'); INSERT INTO USER01.TEST_01 VALUES(2,'测试数据002'); INSERT INTO USER01.TEST_01 VALUES(3,'测试数据003'); INSERT INTO USER01.TEST_01 VALUES(4,'测试数据004');

image.png

  • USER01将TEST_01表授权给USER02
grant SELECT,INSERT,DELETE,UPDATE on USER01.TEST_01 to USER02;
  • USER02模拟误删数据操作
--修改数据 UPDATE USER01.TEST_01 SET C2 = '测试数据003被修改' WHERE C1 = 3; --删除数据 DELETE FROM USER01.TEST_01 WHERE C1 = 4; --查询USER01.TEST_01当前结果集 SELECT * FROM USER01.TEST_01;

image.png

3.3 源库执行全库备份

>SQL backup database full backupset 'D:\dmdbms\data\DAMENG\bak\DB_DAMENG_FULL_2026_0423';

image.png

3.4 源库备份和归档拷贝至分析库环境

  • 拷贝备份
    image.png
  • 拷贝归档日志
    image.png

3.5 分析库还原备份并启动

注:分析库必须要通过源库的备份进行还原恢复,因为DBMS_LOGMNR在解析归档日志时需要依赖源库的数据字典信息(表结构、对象ID等),若直接在一个新实例上对源库归档进行挖掘分析,V$LOGMNR_CONTENTS的结果集为空。

[dmdba@localhost bin]$ /dmdbms/bin/dmrman CTLSTMT="RESTORE DATABASE '/dmdata/DAMENG/dm.ini' FROM BACKUPSET '/dmbak/DB_DAMENG_FULL_2026_0423'" dmrman V8 RESTORE DATABASE '/dmdata/DAMENG/dm.ini' FROM BACKUPSET '/dmbak/DB_DAMENG_FULL_2026_0423' [Percent:100.00%][Speed:0.00M/s][Cost:00:00:02][Remaining:00:00:00] restore successfully. time used: 00:00:03.347 [dmdba@localhost bin]$ /dmdbms/bin/dmrman CTLSTMT="RECOVER DATABASE '/dmdata/DAMENG/dm.ini' FROM BACKUPSET '/dmbak/DB_DAMENG_FULL_2026_0423'" dmrman V8 RECOVER DATABASE '/dmdata/DAMENG/dm.ini' FROM BACKUPSET '/dmbak/DB_DAMENG_FULL_2026_0423' [Percent:100.00%][Speed:0.00PKG/s][Cost:00:00:00][Remaining:00:00:00] recover successfully! time used: 00:00:03.312 [dmdba@localhost bin]$ /dmdbms/bin/dmrman CTLSTMT="RECOVER DATABASE '/dmdata/DAMENG/dm.ini' UPDATE DB_MAGIC" dmrman V8 RECOVER DATABASE '/dmdata/DAMENG/dm.ini' UPDATE DB_MAGIC recover successfully! time used: 00:00:01.311 [dmdba@~]$ /dmdbms/bin/DmServiceDMSERVER start Starting DmServiceDMSERVER: [ OK ]

3.6 dmmdf修改归档DB_MAGIC

3.6.1 MAGIC值介绍及修改原因

  • MAGIC值介绍
    数据库魔数分为PERMANENT_MAGIC和DB_MAGIC,在初始化实例时会生成PERMANENT_MAGIC和DB_MAGIC值。
    PERMANENT_MAGIC称为永久魔数,除了DDL_CLONE还原场景外,一旦生成后,永远不会改变。
    DB_MAGIC称为数据库魔数,同样可以用来标识一个数据库,但是DB_MAGIC是可以变化的,每经过一次还原、恢复操作后, DB_MAGIC就会产生变化,用来区分备份源库和还原目标库。
  • 修改DB_MAGIC的原因
    DBMS_LOGMNR在解析归档日志时,会校验归档日志的DB_MAGIC是否与当前数据库实例的DB_MAGIC匹配。若不一致,工具会认为日志不属于当前实例,报错归档日志MAGIC错误。
    image.png
    当前归档日志的DB_MAGIC值与源库相同,因此需要使用dmmdf工具将其修改为分析库的DB_MAGIC。

3.6.2 查询分析库DB_MAGIC

SQL> SELECT DB_MAGIC FROM DUAL; DB_MAGIC=1912313805

image.png

3.6.3 修改归档DB_MAGIC

使用/dmdbms/bin目录下的dmmdf工具对归档日志的DB_MAGIC进行修改并保存。

[dmdba@localhost dmsetup]$ /dmdbms/bin/dmmdf TYPE=2 FILE=/dmsetup/ARCHIVE_LOCAL1_0x6054DEB1_EP0_2026-04-24_15-10-26.log dmmdf V8 ********************************************************** 1 sig = DMALOG 2 ver = 7007 3 chksum = 595069911 4 sta = 0 5 n_magic = 0 6 db_magic = 1616174769 7 len = 67108864 8 free = 442368 9 clsn = 176958 10 clsn_fil = 0 11 clsn_off = 4096 12 pemnt_magic = 2147483647 13 fil_id = 0 15 next_seq = 7595 16 g_next_seq = 7595 17 arch_lsn = 176261 18 arch_seq = 7535 19 dbversion = 0x7000d 20 min_exec_version = V8.1.1.1 21 min_dct_version = 4 22 p_db_magic = 0 23 n_apply_ep = 0 24 apply_info_lsn = 0 pkg_seq_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) apply_lsn_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 25 recv_p_db_magic = 0 26 recv_n_apply_ep = 0 recv_pkg_seq_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) recv_apply_lsn_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 27 l_term_id = 0 28 term_id = 0 29 c_seqno = 0 30 c_lsn = 0 31 rpkg_crc_stand = 1 ********************************************************** You can only reset sta(4) or db_magic (6) or clsn (9) or clsn_fil(10) or clsn_off(11) or pemnt_magic(12) or fil_id(13) or next_seq(15) or g_next_seq(16) or p_db_magic(22) or n_apply_ep(23). Please input the num which one you want to change, q to quit: 6 Input the new value: 1912313805 ********************************************************** 1 sig = DMALOG 2 ver = 7007 3 chksum = 852968107 4 sta = 0 5 n_magic = 0 6 db_magic = 1912313805 7 len = 67108864 8 free = 442368 9 clsn = 176958 10 clsn_fil = 0 11 clsn_off = 4096 12 pemnt_magic = 2147483647 13 fil_id = 0 15 next_seq = 7595 16 g_next_seq = 7595 17 arch_lsn = 176261 18 arch_seq = 7535 19 dbversion = 0x7000d 20 min_exec_version = V8.1.1.1 21 min_dct_version = 4 22 p_db_magic = 0 23 n_apply_ep = 0 24 apply_info_lsn = 0 pkg_seq_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) apply_lsn_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 25 recv_p_db_magic = 0 26 recv_n_apply_ep = 0 recv_pkg_seq_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) recv_apply_lsn_arr: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 27 l_term_id = 0 28 term_id = 0 29 c_seqno = 0 30 c_lsn = 0 31 rpkg_crc_stand = 1 ********************************************************** Do you want to quit and save the change to file (y/n): y Save to file success!

3.7 挖掘归档恢复数据的过程

用户可以使用 DBMS_LOGMNR 包对归档日志进行挖掘,重构出DDL和DML 等操作,并通过获取的信息进行更深入的分析(目前DBMS_LOGMNR只支持对归档日志进行分析)。

3.7.1 构建DBMS_LOGMNR系统包

SQL> SP_CREATE_SYSTEM_PACKAGES(1,'DBMS_LOGMNR');

3.7.2 添加归档日志路径

成功构建DBMS_LOGMNR系统包后,通过DBMS_LOGMNR.ADD_LOGFILE添加归档日志路径。需要注意的是,添加归档日志的操作只能在START之前进行。

SQL> CALL DBMS_LOGMNR.ADD_LOGFILE('/dmsetup/ARCHIVE_LOCAL1_0x6054DEB1_EP0_2026-04-24_15-10-26.log');

image.png

--DBMS_LOGMNR.ADD_LOGFILE参数说明 LogFileName:增加的文件的全路径。 Options:可选配置参数(默认为DBMS_LOGMNR.ADDFILE),具体的可选配置包括: DBMS_LOGMNR."NEW"结束当前LOGMNR(调用 LOGMNR_END),并增加指定文件(如果已经 START,则不可增加); DBMS_LOGMNR.ADDFILE 在当前 LOGMNR 中增加日志文件(如果已经 START,则不可增加); DBMS_LOGMNR.REMOVEFILE 从当前 LOGMNR 中去除一个日志文件 RAFTID:主要是针对DPC环境,用于指定RAFT组的RAFT_ID。非DPC环境可以忽略该参数。

3.7.3 查询已添加的归档日志

通过V$LOGMNR_LOGS动态视图查询已添加的归档日志文件。

SQL> SELECT LOW_SCN,NEXT_SCN,LOW_TIME,HIGH_TIME,LOG_ID,FILENAME FROM V$LOGMNR_LOGS;

image.png

3.7.4 执行归档日志分析

通过DBMS_LOGMNR.START_LOGMNR启动归档日志分析。

SQL> DBMS_LOGMNR.START_LOGMNR(OPTIONS=>2130);

image.png
注:同一个会话中只能同时启动一个START_LOGMNR,具体报错如下图所示。
image.png

3.7.5 查看归档日志分析结果

通过V$LOGMNR_CONTENTS动态视图查询归档日志的分析结果。

SQL> SELECT * FROM V$LOGMNR_CONTENTS;

image.png
注:仅当执行DBMS_LOGMNR.START_LOGMNR();后,才能查询V$LOGMNR_CONTENTS,否则会报错。

image.png

3.7.6 定位误操作

  • 过滤结果集
    生产环境的事务极其频繁,单纯依靠人工一条条看V$LOGMNR_CONTENTS基本不现实。实际排查时,可以利用结果集中的关键字段信息进行过滤筛选,先根据业务发现异常的大概时间缩小范围,再看涉及的模式和表名,最后按操作类型精准找出那条误操作。
SELECT SCN AS "当前记录的LSN", START_SCN AS "当前事务起始LSN", COMMIT_SCN AS "当前事务截止LSN", TIMESTAMP AS "当前记录创建时间", START_TIMESTAMP AS "当前事务开始时间", COMMIT_TIMESTAMP AS "当前事务截止时间", OPERATION AS "操作类型", OPERATION_CODE AS "操作类型编号", SQL_REDO AS "SQL语句", SEG_OWNER AS "被操作模式名", TABLE_NAME AS "被操作表名", USERNAME AS "操作者", SESSION# AS "当前记录会话id", SESSION_INFO AS "SQL来源的IP" FROM V$LOGMNR_CONTENTS WHERE TIMESTAMP BETWEEN '2026-04-24 15:30:00' AND '2026-04-24 15:40:00' AND SEG_OWNER = 'USER01' AND TABLE_NAME = 'TEST_01' AND OPERATION IN ('DELETE', 'UPDATE');
  • 定位误操作记录
    经过滤后,定位到用户USER02对USER01.TEST_01表误操作的具体信息。
    image.png
    image.png
    image.png

3.7.7 恢复数据

基于3.7.6章节定位到的UPDATE和DELETE误操作记录,编写并执行相应的逆向回滚语句,完成USER01.TEST_01表的数据恢复并查询验证。

UPDATE USER01.TEST_01 SET C2 = '测试数据003' WHERE C1 = 3; INSERT INTO USER01.TEST_01 VALUES(4,'测试数据004'); COMMIT;

查询USER01.TEST_01结果集。
image.png

3.7.8 追溯误操作用户和IP地址

通过挖掘分析归档日志的结果集,可以看到对USER01.TEST_01进行误操作(修改和删除)的用户是USER02,并且按照《DM8系统管理员手册》中的解释,V$LOGMNR_CONTENTS的SESSION_INFO字段会记录SQL来源的IP地址,但是在测试过程中,该字段并没有记录IP。
image.png

image.png
在理想情况下(对源库进行误操作的会话连接仍未关闭),可以通过VLOGMNR_CONTENTS中的SESSION#字段存储的当前记录会话ID,到源库中通过VSESSIONS定位IP地址。

SELECT SESS_ID,STATE,CREATE_TIME,CLNT_HOST,APPNAME,CLNT_IP FROM V$SESSIONS WHERE SESS_ID = 2058081336;

image.png
若对源库进行误操作的会话连接已经关闭,可以通过VSESSION_HISTORY定位操作用户的信息,VSESSION_HISTORY虽然没有VSESSIONS记录的信息全面(主要区别在于VSESSION_HISTORY不会记录动态改变的信息,例如会话状态、SQL语句等),但V$SESSION_HISTORY会记录用户名、IP等信息。

需要注意的是,查询VSESSION_HISTORY的方式也不是永久有效的,VSESSION_HISTORY里的记录信息存储在内存中,数据库重启后就会清空,记录上限为10000条,当到达上限后会覆盖最旧的历史会话记录。

SELECT SESS_ID,CREATE_TIME,CLNT_HOST,APPNAME,CLNT_IP FROM V$SESSION_HISTORY WHERE SESS_ID = 2058081336;

image.png

3.7.9 停止归档日志分析

SQL> DBMS_LOGMNR.END_LOGMNR();

image.png

4 附录

4.1 保留分析结果

由于 V$LOGMNR_CONTENTS 仅在执行DBMS_LOGMNR.START_LOGMNR()后才可访问,且随日志分析会话结束而失效,因此可在分析期间将所需数据导出并保存至新建的物理表中。这样即便后续关闭归档分析或结束会话,仍可随时查询和分析历史归档日志的分析结果。

--存放历史归档日志分析结果 CREATE TABLE ARCH_LOG AS SELECT * FROM V$LOGMNR_CONTENTS WHERE SEG_OWNER = 'USER_NAME' AND OPERATION_CODE IN (1,2,3,5); --OPERATION_CODE字段说明 OPERATION_CODE存储SQL操作类型。 1:插入,2:删除,3:修改,4:批量修改,5:DDL操作,6:START7COMMIT36ROLLBACK37:SEQ MODIFY38:XA_COMMIT,255:UNSUPPORTED。

4.2 未开启RLOG_APPEND_LOGIC

经测试,当RLOG_APPEND_LOGI参数未开启时,DBMS_LOGMN加载与分析归档日志的整个流程均可正常执行,但由于日志中缺乏逻辑操作信息,最终查询 V$LOGMNR_CONTENTS的结果集为空。
image.png

4.3 RLOG_APPEND_LOGIC参数影响

当RLOG_APPEND_LOGIC=1时,若数据表存在主键列,执行UPDATE或DELETE操作仅会记录条件列和主键列的值;若数据表不存在主键列,执行UPDATE或DELETE操作会记录所以列的值。

  • 测试数据
--USER01.TEST_02带主键 CREATE TABLE USER01.TEST_02(C1 INT PRIMARY KEY,C2 VARCHAR(30),C3 VARCHAR(30)); INSERT INTO USER01.TEST_02 VALUES(1,'T2_001','A'); INSERT INTO USER01.TEST_02 VALUES(2,'T2_002','B'); INSERT INTO USER01.TEST_02 VALUES(3,'T2_003','C'); INSERT INTO USER01.TEST_02 VALUES(4,'T2_004','D'); UPDATE USER01.TEST_02 SET C2 = 'T2_001_update' WHERE C1 = 1; DELETE FROM USER01.TEST_02 WHERE C1 = 2; --USER01.TEST_03不带主键 CREATE TABLE USER01.TEST_03(C1 INT,C2 VARCHAR(30),C3 VARCHAR(30)); INSERT INTO USER01.TEST_03 VALUES(1,'T3_001','A'); INSERT INTO USER01.TEST_03 VALUES(2,'T3_002','B'); INSERT INTO USER01.TEST_03 VALUES(3,'T3_003','C'); INSERT INTO USER01.TEST_03 VALUES(4,'T3_004','D'); UPDATE USER01.TEST_03 SET C2 = 'T3_001_update' WHERE C1 = 1; DELETE FROM USER01.TEST_03 WHERE C1 = 2;
  • 数据表存在主键(USER01.TEST_02)
    image.png
    image.png

  • 数据表不存在主键(USER01.TEST_03)
    image.png
    image.png

  • 结论
    建议将RLOG_APPEND_LOGIC设置为2,该取值表示不论数据表是否含有主键列,都会在UPDATE和DELETE操作时记录所有列的值(不包含大字段列),可显著提升日志挖掘的恢复能力,便于找回误删或误改的数据。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服