ORACLE数据库中如何找到过去某个时间某个表被谁修改了
目录
一.问题描述
二.现场环境:
三、Oracle loginer 工具介绍
四、具体分析步骤
4.1. 确定时间
4.2 确定归档日志文件
4.3.向LogMiner 会话添加 redo 日志文件
4.3.1 添加第一个文件
4.3.2 脚本式添加日志文件
4.3.3 执行添加动作
4.4.启动分析
4.5.创建结果表
4.6.结束分析
4.7.根据情况查找指定的记录:
五、总结一下:
一.问题描述
一张表被修改了,初步估计在2025年11月10日10:10--10:30被修改了,能否帮忙查一下是谁修改的?
类似:
这个字段的值被修改了,我自己没有修改过,帮忙查看一下是谁在哪台机器上修改的?
最近归档日志切换产生太大了,一台都要产生700G,能帮忙分析一下原因吗?
对于这些问题,日常中,可能碰到比较多,有没有办法处理呢?
二.现场环境:
ORACLE 19C + RAC+ LINUX
当然,对于类似问题,如果有数据库审计系统,可能比较方便查找,但大部分场景下,是没有数据库审计的,那如果没有审计,就不能处理了吗?
答案是肯定的,我们可以利用ORACLE logminer功能来处理。
三、Oracle loginer 工具介绍
Oracle loginer,是Oracle数据库自带的功能,从Oracle 9i后,可以在线分析,步骤相对简单,不需要对数据库做额外设置。如果数据在联机日志文件中,可以直接对REDO LOGFILE进行分析,否则,我们可以针对归档日志进行分析。分析归档日志,如果是很久以前的归档日志,需要从备份中,把归档日志还原出来。然后,在进行分析。这个对归档日志的分析,可以在原主机分析,也可以在其他机器分析。
四、具体分析步骤
下面就这里提到的问题,我们使用 logminer工具来进行分析:
4.1. 确定时间
我们这里提到了 11月10日10:10--10:30,那就是业务发生时间在2025年11月10日 10:10-10:30 。
4.2 确定归档日志文件
由于11月10日,是4天以前的事情了,我们需要确定这个归档日志是否还在磁盘上,否则,需要从备份中还原。
select thread#,sequence#,name,to_char(first_time,'yyyy-mm-dd hh24:mi:ss')
from v$archived_log
where first_time between to_date('2025-11-10 10:00:00','yyyy-mm-dd hh24:mi:ss')
and to_date('2025-11-10 10:30:00','yyyy-mm-dd hh24:mi:ss')
and CREATor='ARCH'
order by 1,2;
THREAD# SEQUENCE# NAME TO_CHAR(FIRST_TIME,
---------- ---------- ---------------------------------------------------------------------- -------------------
1 164162 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164162.12677.1216807805 2025-11-10 10:01:17
1 164163 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164163.15814.1216808391 2025-11-10 10:10:05
1 164164 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164164.12720.1216809077 2025-11-10 10:19:50
2 158031 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158031.12715.1216807881 2025-11-10 10:01:59
2 158032 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158032.14602.1216808535 2025-11-10 10:11:20
2 158033 +DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158033.13583.1216809197 2025-11-10 10:22:14

去ASM磁盘组检查一下,这些归档日志是否还在。如果不存在,还需要从备份中还原出来。我们这里,正好还在,就不要从备份中还原。
由于我们这里是ASM,如果你想从ASM磁盘组中取出来,放到其他机器,比如文件系统,还需要通过ASMCMD CP 方式把文件拷出来,我这里本次没有这个需要,可以忽略。
4.3.向LogMiner 会话添加 redo 日志文件
我们可以使用execute sys.dbms_logmnr.add_logfile()语句添加要分析的归档日志
4.3.1 添加第一个文件
第一个文件,需要使用 execute sys.dbms_logmnr.add_logfile(归档日志文件,options=>sys.dbms_logmnr.new),
其他文件,直接
execute sys.dbms_logmnr.add_logfile(归档日志文件)即可。
4.3.2 脚本式添加日志文件
这里日志比较少,手工一个个添加即可,但如果归档日志比较多呢(一般要分析的比较少),可以直接生成脚本方式来处理。
如下:
select 'execute sys.dbms_logmnr.add_logfile(logfilename=>''' || name || '''' || decode(rownum,1,',options=>sys.dbms_logmnr.new','') || ');' as sqlstat
from v$archived_log
where first_time between to_date('2025-11-10 10:00:00','yyyy-mm-dd hh24:mi:ss')
and to_date('2025-11-10 10:30:00','yyyy-mm-dd hh24:mi:ss')
and CREATor='ARCH'
order by first_time, thread# desc ,sequence#;
自动产生要分析的归档日志:
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164162.12677.1216807805',options=>sys.dbms_logmnr.new);
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158031.12715.1216807881');
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164163.15814.1216808391');
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158032.14602.1216808535');
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_1_seq_164164.12720.1216809077');
execute sys.dbms_logmnr.add_logfile(logfilename=>'+DATA/HISDB/ARCHIVELOG/2025_11_10/thread_2_seq_158033.13583.1216809197');
执行以上脚本。

4.3.3 执行添加动作

4.4.启动分析
execute sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.DICT_FROM_ONLINE_CATALOG);

4.5.创建结果表
我们可以直接对 v$logmnr_contents 进行分析,但会占用内存,影响系统。一般我们是对 v$logmnr_contents 创建一个表,后面通过其他工具,比如PLSQL DEVELOPER等图形界面工具慢慢分析。
create table logmnr_contents_251110 as select * from v$logmnr_contents;

不过,需要注意,如果这个记录比较多,需要考虑一下这个表放到哪个表空间,上面命令默认放到SYSTEM表空间,因此,需要确定SYSTEM表空间剩余空间是否足够。具体步骤略。
4.6.结束分析
exec sys.dbms_logmnr.end_logmnr;

之后,可以就不影响当前系统。
4.7.根据情况查找指定的记录:
比如我们这里,想找 谁修改了 PTS.PAI_ADMISSION_NOTICE.
那么就可以使用下面的语句:
select SQL_REDO,operation,username,client_info,timestamp
from sys.logmnr_contents_251110
where seg_owner='PTS'
AND SEG_NAME='PAI_ADMISSION_NOTICE'
and operation='UPDATE'
order by timestamp ;

当然,还可以确认一下这个时间段,主要的UPDATE,主要时间段,

数据在手,想怎么分析,看你自己。
至此,我们找到我们想要的结果。
五、总结一下:
在ORACLE数据中,如果要想查看过去的DML操作,我们直接使用ORACLE原生的LOGMINER工具,直接分析过去的归档日志解决。
