Oracle的日志挖掘,是一种数据恢复技术,只需要你的归档日志(Archivelog)和重做日志(redo log)完整,即可将数据恢复到你想要的任意时刻。在这里,就让我首先说说重做日志挖掘。
先来说说redo。
redo日志挖掘是基于重做日志(redo log)的基础之上进行的挖掘恢复操作。那么,做为Oracle的重要特性之一的redo,它用来保证事务的可恢复和可回退。也就是说,它可以重演事务,从而使得在数据库发生故障之后,数据可以被恢复。redo对于Oracle数据库来说是相当重要的。
redo的三大件 redo log buffer、LGWR、redo log file。所以,redo的功能主要通过这三大组件来实现。
redo log buffer重做日志缓冲区是Oracle数据库SGA中最小的一个内存结构。重做日志缓冲区是一个循环使用的内存缓冲区,它以重做日志条目(redo log entries)的形式存储。当它写满时,新的重做日志条目(redo log entries)将从缓冲区的起始位置开始写入,覆盖旧的数据。
重做日志条目(redo log entries)是由用户进程生成的,它包含了重构、重做数据库变更的重要信息,这些变更包括INSERT,UPDATE,DELETE,CREATE,ALTER 或者 DROP 等。在必要的时候重做日志条目(redo log entries)被用于数据库恢复。当用户进程执行这些操作时,会生成相应的重做日志条目(redo log entries),所以这些条目中记录了执行的数据操作、事务信息等 。
当用户进程生成重做日志条目(redo log entries),首先被存储在重做日志缓冲区(redo log buffer)中[PGA-->SGA],然后由LGWR(log writer)进程将重做日志缓冲区(redo log buffer)中的数据写入到磁盘上的在线重做日志组(online redo log)中。这个过程,保证了数据的一致性和持久性,即使数据库发生故障,也可以通过重做日志文件(redo log file)来恢复数据。
redo log buffer是循环使用的,当LGWR进程不断地把redo log buffer的内容写出到redo log file中,写入到online redo log中。redo log file同样是循环使用的。
LGWR(log writer)后台进程,将日志缓冲内容写到磁盘的在线重做日志文件或组(online redo log)中。DBWR则是将数据块分散写入磁盘(落盘)。
当然,以上的过程,都是在数据commit时,将变更写入在线重做日志(online redo log)中。
基本就这么个意思了。
其它相关的还有SGA中的种池、DBWN、检查点、归档,在这里不详述。以上说了这么说,无非就是要告诉你,redo的基本操作,它这一趟子走下来,最终把数据丢哪儿了。然后,接下来,我们找东西。
挖掘过程是这样的。
当数据库在运行过程中,会发生许许多多的操作,当然包括以上的INSERT,UPDATE,DELETE,CREATE,ALTER 或者 DROP 等,而所有的这些操作都会被记录在redo日志中。redo日志也记录undo日志,所以也可使用redo日志中的undo日志,对所做的操作进行回退。那么,只要明确了要恢复的操作记录在哪个时间范围内,就可以通过时间或者scn号将要恢复的操作写入到v$logmnr_contents视图中,然后找到对应的undo记录,执行undo记录的sql语句,就可将数据恢复到更改前的状态。
0.测试数据
create table baoyw (id int,name varchar(60));
insert into baoyw values (1,'北京’);
insert into baoyw values (1,'北京’);
insert into baoyw values (1,'北京’);
commit;
1.格式化当前时间显示
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session alerted.
SQL>
2.查看系统是否运行在归档模式
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /oracle/app/oracle/archive/
Oldest online log sequence 3549
Next log sequence to archive 3551
Current log sequence 3551
SQL>
如果没有开启归档,在mount下开启归档。
3.启用最小日志。
--开启最小日志
alter database add supplemental log data;
--
alter database add supplemental log data (primary key) columns;
--
alter database add supplemental log data (unique) columns;
--
alter database add supplemental log data (primary key, unique index) columns;
4.查询日志状态 NO关闭 YES开启
--默认开启最小日志
SQL> select SUPPLEMENTAL_LOG_DATA_MIN,SUPPLEMENTAL_LOG_DATA_PK,SUPPLEMENTAL_LOG_DATA_UI,SUPPLEMENTAL_LOG_DATA_FK,SUPPLEMENTAL_LOG_DATA_ALL from v$database;
SUPPLEME SUP SUP SUP SUP
-------- --- --- --- ---
YES NO NO NO NO
SQL>
5.修改一条数据
SQL> update baoyw set name = '重庆' where id = '2';
1 row updated.
SQL> commit;
Commit complete.
SQL> select sysdate from dual;
SYSDATE
-------------------
2024-03-11 18:20:30
SQL> select * from baoyw;
ID NAME
----------- ---------------------------------
1 北京
2 重庆
3 宁夏
SQL>
6.开启日志挖掘
将需要挖掘的时间段的日志,写入到v$logmnr_contents视图中。
使用在线字典自动加载。
以时间范围加载日志。
--开启日志挖掘
--调用相应的存储过程,除时间外,其他都是固定参数
SQL> begin
2 dbms_logmnr.start_logmnr(
3 starttime=>to_date('2024-03-11 18:20:00','yyyy-mm-dd hh24:mi:ss'),
4 endtime=>to_date('2024-03-11 18:22:14','yyyy/mm/dd hh24:mi:ss'),
5 options=>dbms_logmnr.dict_from_online_catalog + dbms_logmnr.continuous_mine);
6 end;
7 /
PL/SQL procedure successfully completed.
SQL>
7.手动切换归档
手动切换可有可无。
--手动切换归档 将redo记录写入到datafile,并形成归档
alter system checkpoint;
alter system switch logfile;
8.查询视图 v$logmnr_contents
sql_redo 是你操作过程的关键字。
如果只通过seg_name条件,将得到一定时间范围内,此用户的所有操作。
seg_name 是更改的表名,seg_owner是表所属的用户,sql_redo是redo日志记录的sql信息。
sql_undo 就是你的回退sql 用这条sql就可以将数据恢复到更改前的状态。
SQL>SELECT sql_undo
2 FROM v$logmnr_contents
3 AND seg_name = 'BAOYW'
4 AND sql_redo LIKE 'update%';
SQL_UNDO
------------------------------------------------------------------------------
update "SYS"."BAOYW" set "NAME" = '天津' where "ID" = '2' and "NAME" = '重庆‘
and ROWID = 'aaawG9AABAAAXspAAB';
SQL>
9.执行undo字段中的sql
SQL> update "SYS"."BAOYW" set "NAME" = '天津' where "ID" = '2' and "NAME" = '重庆‘ and ROWID = 'aaawG9AABAAAXspAAB';
1 row updated.
SQL> select * from baoyw;
ID NAME
----------- ---------------------------------
1 北京
2 天津
3 宁夏
SQL> commit;
Commit complete.
SQL>
10.关闭日志挖掘
退出当前会话,即可关闭日志挖掘。
--关闭日志挖掘
begin
dbms_logmnr.end_logmnr;
end;
/
11.其他
--日志
SELECT GROUP#,
THREAD#,
SEQUENCE#,
BYTES,
BLOCKSIZE,
MEMBERS,
ARCHIVED,
STATUS, FIRST_CHANGE#, to_char(FIRST_TIME, 'yyyy-mm-dd hh24:mi:ss') FIRST_TIME, NEXT_CHANGE#, to_char(NEXT_TIME, 'yyyy-mm-dd hh24:mi:ss') NEXT_TIME
FROM v$log;
col MEMBER for a65
select * from v$logfile;
select * from v$log;
select * from v$archived_log;