oracle重做日志详解,oracle重做日志分析

日志文件的块大小查询

日志文件的块大小可以通过如下方法来查询:

select distinct block_size from v$archived_log;

清理脏块

将所有的脏块给清到磁盘上

alter system flush buffer_cache

查询日志分组信息

select * from v$log;

查询当前日志分组

select * from v$log where status='CURREN';

创建日志分析存储过程以及查询常见信息

# 加载字典至文件 /u01/app/logminer/dictionary.ora,需要目录和文件的所有者所数组是 oracle:dba

exec dbms_logmnr_d.build( 'dictionary.ora', '/u01/app/logminer'); # 可选

# 加载日志

exec dbms_logmnr.add_logfile('/usr/lib/oracle/xe/app/oracle/flash_recovery_area/XE/onlinelog/o1_mf_1_djfw9s0s_.log', dbms_logmnr.NEW);

# 再加载日志,可选

exec dbms_logmnr.add_logfile('/usr/lib/oracle/xe/app/oracle/flash_recovery_area/XE/onlinelog/o1_mf_1_djfw9s0s_.log', dbms_logmnr.ADDFILE);

# 启动logminer

dbms_logmnr.start_logmnr(DictFileName=>'/u01/app/logminer/dictionary.ora');

至此,存储已经创建好,根据需要,字典可以选择加载或不加载,一般在是在执行DDL之后需要重新加载字典,接下来查询常见信息

select SCN,INFO,to_char(timestamp,'yyyy-mm-dd hh24:mi:ss'),table_name,OPERATION,SQL_REDO,SQL_UNDO,status from v$logmnr_contents;

测试记录

只用 ID 作为条件且只更新 LOB 字段(SQL_REDO 和 SQL_UNDO 中缺失 条件)

无主键表

create table event

(

id number,

name varchar2(20),

a_blob blob,

a_clob clob

);

insert into event (id,name,a_blob,a_clob) values(1,'11','01010101010101','test-clob');

update event set a_blob = null where id =3;

## where 后面的条件缺失

----- sql_redo = update "SYSTEM"."EVENT" set "A_BLOB" = NULL where ;

----- sql_undo = update "SYSTEM"."EVENT" set "A_BLOB" = NULL where ;

有主键表

create table event

(

id number primary key,

name varchar2(20),

a_blob blob,

a_clob clob

);

insert into event (id,name,a_blob,a_clob) values(1,'11','01010101010101','test-clob');

update "SYSTEM"."EVENT" set "A_BLOB" = NULL where ;

### where 后面的条件缺失

-----> sql_redo = update "SYSTEM"."EVENT" set "A_BLOB" = NULL where ;

-----> sql_undo = update "SYSTEM"."EVENT" set "A_BLOB" = NULL where ;综上,可以排除未设主键的原因

update event set a_blob = null,name = 'xx' where id =1;

--sql_redo : update "SYSTEM"."EVENT" set "NAME" = 'xx' where "NAME" = '11';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "NAME" = 'xx';

--sql_undo : update "SYSTEM"."EVENT" set "NAME" = '11' where "NAME" = 'xx';

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "NAME" = 'xx';条件中虽然 ID 字段缺失,但是被更新的字段除了 Lob 之外其对于的旧值出现在 where 子句中,有个猜想,如下测试:

update event set a_blob = null,id = 1 where id =1;

--sql_redo : update "SYSTEM"."EVENT" set "ID" = '1', "A_BLOB" = EMPTY_BLOB() where "ID" = '1';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1';

--sql_undo : update "SYSTEM"."EVENT" set "ID" = '1', "A_BLOB" = NULL where "ID" = '1';

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1'再如:

update event set a_blob = null,name='bbb',id = 1 where id =1;

--sql_redo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = 'bbb', "A_BLOB" = EMPTY_BLOB() where "ID" = '1' and "NAME" = 'aaa';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1' and "NAME" = 'bbb';

--sql_undo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = 'aaa', "A_BLOB" = NULL where "ID" = '1' and "NAME" = 'bbb';

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1' and "NAME" = 'bbb';通过测试发现,除了 ID 字段,所有被修改的非 LOB 字段的旧值都会出现在 SQL_REDO 和 SQL_UNDO 的 where 子句中。 为了避免在单独的以 ID 作为标识修改 LOB 字段时导致的在 SQL_REDO 和 SQL_UNDO 中条件缺失的问题,应该在 set 子句 中指定 ID 字段的值,尽管 ID 字段并没有修改

update event set a_blob = null,name = '1-1',id = 1 where id =1;

## 注意此处的 EMPTY_BLOB()

--sql_redo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = '1-1', "A_BLOB" = EMPTY_BLOB() where "ID" = '1' and "NAME" = 'xx';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

--sql_undo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = 'xx', "A_BLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

update event set a_blob = null,a_clob = null ,name = '1-1',id = 1 where id =1;

## 注意此处的 EMPTY_BLOB()

--sql_redo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = '1-1', "A_BLOB" = EMPTY_BLOB() where "ID" = '1' and "NAME" = '1-1';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL, "A_CLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

--sql_undo : update "SYSTEM"."EVENT" set "ID" = '1', "NAME" = '1-1', "A_BLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL, "A_CLOB" = NULL where "ID" = '1' and "NAME" = '1-1';

更新BLOB字段内容(BLOB字段无法通过 SQL_UNDO 还原)

>表中 id 为 1 的记录字段 a_blob 非空:insert into event (id,name,a_blob,a_clob) values(1,'11','01010101010101','test-clob');

update event set a_blob = '1010101',name = 'aaa' where id =1;

--sql_redo : update "SYSTEM"."EVENT" set "NAME" = 'aaa', "A_BLOB" = EMPTY_BLOB() where "NAME" = '1-1';

--sql_redo : update "SYSTEM"."EVENT" set "A_BLOB" = HEXTORAW('01010101') where "NAME" = 'aaa';

--sql_undo : update "SYSTEM"."EVENT" set "NAME" = '1-1', "A_BLOB" = NULL where "NAME" = 'aaa';

## 最终只是把 a_blob 的设置为 NULL,并不是原来的 '01010101010101'

--sql_undo : update "SYSTEM"."EVENT" set "A_BLOB" = NULL where "NAME" = 'aaa';

如果使用 activeJDBC 形式 ,执行 update event set a_blob = 'read bytes[] from a file',name = 'aaa' where id =1;

日志中根本就没有出现 a_blob 字段

-- sql_undo : update "SYSTEM"."EVENT" set "ID" = '1' where "ID" = '1';

sqldeveloper 和 jdbc 执行含 LOB 字段(超过4K)的 insert 对比含 LOB 字段的 insert 操作,数据库均会先执行 insert 非 LOB 字段的内容,之后再 update LOB 字段的内容。 使用 sqldeveloper 界面 insert 含 LOB 字段的记录时,日志中的 insert 和 update 的 SCN 是相同的,而 使用 java 代码通过 activeJDBC insert 含 LOB 字段的记录时,日志中的 insert 和 update 的 SCN 是不 相同的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值