基础知识补漏-redo

redo


数据库变更的相关信息。这些信息以重做条目(Redo Entries)形式存储。


Redo Entries 的内容被 Oracle 数据库进程从用户的内存空间(PGA)复制到 SGA 中的 Redo Log Buffer 之中。Redo Entries 在内存中占用连续的顺序空间,由于 Redo Log Buffer 是循环使 用的,Oracle 通过一个后台进程 LGWR 不断的把 Redo Log Buffer 的内容写出到 Redo Log File 中,Redo Log File 同样是循环使用的。


检查点只是一个数据库事件,它存在的根本意义 在于减少恢复时间。


Redo copy latch 表明进程正在把 redo 拷贝入 log buffer 中.


为了避免 LGWR 被不必要的通知,进程需要先获取 redo writing latch 去检查 LGWR 是否已经激活或者已经被通知。如果 redo writing latch 竞争过多,可能意味着你的 交过于频繁。


latch数目是cpu的两倍。


获得相关 Latch 信息
SELECT substr(ln.name, 1, 20), gets, misses, immediate_gets, immediate_misses FROM v$latch l, v$latchname ln
WHERE ln.name in ('redo allocation', 'redo copy') and ln.latch# = l.latch#;
如果MISSES对GETS比率超过1%,或者IMMEDIATE_MISSES 对 (IMMEDIATE_GETS + IMMEDIATE_MISSES) 比率超过 1%,那么通常认为存在 Latch 竞争。


当主机拥有 16~64 个 CPU 时,Oracle 公司推荐设置 LOG_PARALLELISM 在 2~8 之间。


Redo Copy 正是引发 Redo Allocation Latch 竞争的根源。


事务的恢复,必须以 Redo Record 为最小 单位。


日志分析获取篡改信息案例:
用户遭遇的具体问题为:
login_name=7847254的balance字段数据被恶意修改,客户反映数据被修改的时间段为 7.5-7.6日9:00,balance字段被修改为40000。客户于7.6日上午11:00将此值重置为0.


首先获取该行记录的 ROWID 等信息:
SQL> select rowid from "CINMS"."BROAD_SUBSCRB" where login_name='7847254'; ROWID
------------------
AAAQXKAAvAAAB2wAAn


根据 ROWID 可疑找到该记录的块号等信息:
SQL> select get_rowid('AAAQXKAAvAAAB2wAAn') from dual;
GET_ROWID('AAAQXKAAVAAAB2WAAN') 
-------------------------------------------------------------------------------- Object# is :67018
Relative_fno is :47
Block number is :7600
Row number is :39


get_rowid 是根据 dbms_rowid 包编写的一个函数,用于简化 ROWID 拆分,其代码如下:
create or replace function get_rowid (l_rowid in varchar2)
return varchar2
is
ls_my_rowid varchar2(200); rowid_type number; object_number number; relative_fno number; block_number number; row_number number;
begin dbms_rowid.rowid_info(l_rowid,rowid_type,object_number,relative_fno,
row_number);
ls_my_rowid := 'Object# is :'||to_char(object_number)||chr(10)||
'Relative_fno is :'||to_char(relative_fno)||chr(10)|| 'Block number is :'||to_char(block_number)||chr(10)|| 'Row number is :'||to_char(row_number);
return ls_my_rowid ; end;
/


我们可疑看到,被修改的数据行位于文件 47 的 Block 号 7600 上.通过 Logminer 解析日 志,可疑找到所有对于这个数据块的修改.
解析日志的步骤如下:
SQL> EXECUTE DBMS_LOGMNR.ADD_LOGFILE(LogFileName => '/ora_arch_backup/201107arch/1_12446.dbf',Options => DBMS_LOGMNR.NEW);
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.COMMITTED_DATA_ONLY);
PL/SQL procedure successfully completed.


解析完成之后,可疑通过 v$logmnr_contents 视图来查找相关的修改操作.在该日志中,
解析后共得到约 18 万行数据:
SQL> select count(*) from v$logmnr_contents;
  COUNT(*)
----------
    182001
对数据块 7600 的修改只有一次:
SQL> select count(*) from v$logmnr_contents where DATA_BLK#=7600;
  COUNT(*)
----------
         1


该修改正是位于 BROAD_SUBSCRB 表,但是 SQL_REDO 和 SQL_UNDO 信息不可用:
SQL> select scn,seg_name,sql_redo,sql_undo,rs_id from v$logmnr_contents where scn=5568491262; SCN SEG_NAME SQL_REDO SQL_UNDO RS_ID
---------- --------------- ------------ ------------ -------------------------
5568491262 BROAD_SUBSCRB Unsupported Unsupported 0x00309e.00028a0a.0010
SQL> select scn,session#,sql_redo,sql_undo,rs_id from v$logmnr_contents where DATA_BLK#=7600;
SCN SESSION# SQL_REDO SQL_UNDO RS_ID
---------- ---------- ------------ ------------ ------------------------------ 5568491262 90 Unsupported Unsupported 0x00309e.00028a0a.0010


根据 session#,可以将这个会话的所有操作查询出来,注意第一条信息的绝对文件号是 2,也 就是 UNDO 表空间,说明该条目记录的是事务相关信息;第二条信息记录的是对于绝对文件号 47 块号 7602 号的操作:
SQL> select ABS_FILE#,REL_FILE#,DATA_BLK#,DATA_OBJ#,SEG_NAME ,rs_id from v$logmnr_contents
where session#=90 and
ABS_FILE# REL_FILE# ---------- ----------
seg_name='BROAD_SUBSCRB';
DATA_BLK# DATA_OBJ# SEG_NAME RS_ID
---------- ---------- --------------- ------------------------------
7600 66237 BROAD_SUBSCRB 0x00309e.00028a0a.0010
7602 66237 BROAD_SUBSCRB 0x00309e.00028b4d.0010 TIMESTAMP,ABS_FILE#,REL_FILE#,DATA_BLK#,DATA_OBJ#,sql_redo from
2 47
47 47
SQL> select
v$logmnr_contents where session#=90 and seg_name='BROAD_SUBSCRB';
TIMESTAMP ABS_FILE# REL_FILE# DATA_BLK# DATA_OBJ# SQL_REDO ------------------- ---------- ---------- ---------- ---------- ------------------------- 2011-07-05 16:41:38 2 47 7600 66237 Unsupported
2011-07-05 16:41:54 47 47 7602 66237 Unsupported


根据前面查询到的 scn 等信息,可以再次搜索,获取用户的连接信息等,根据这些连接信息, 已经可以确定连接的客户端:
SQL> select session_info from v$logmnr_contents where scn=5568491262;
SESSION_INFO ----------------------------------------------------------------------------------------- -------------------------------------------
login_username=CINMS client_info= OS_username=Administrator Machine_name=WORKGROUP\ANY login_username=CINMS client_info= OS_username=Administrator Machine_name=WORKGROUP\ANY


某日全天的日志生成可以通过如下查询计算
select trunc(COMPLETION_TIME),sum(Mb)/1024 DAY_GB from
(select name,COMPLETION_TIME,BLOCKS*BLOCK_SIZE/1024/1024 Mb from v$archived_log where COMPLETION_TIME between trunc(sysdate) -2 and trunc(sysdate) -1)
group by trunc(COMPLETION_TIME)
/


最近日期的日志生成统计
SELECT TRUNC (completion_time), SUM (mb) / 1024 day_gb
FROM (SELECT NAME, completion_time, blocks * block_size / 1024 / 1024 mb FROM v$archived_log)
GROUP BY TRUNC (completion_time);


Oracle 的隐含参数_wait_for_sync 参数可以设置为 false 避免 redo file sync 的等待,但是就 将无法保证事务的恢复性。


log文件Active 状态意味着,检查点尚未完成,如果日志文件循环使用再次到达该文件,
数据库将处于等待的停顿状态.


Checkpoint incomplete 有多种可能原因:
1. 日志文件过小,切换过于频繁
2. 日志组太少,不能满足正常事务量的需要
3. 日志文件所在磁盘 I/O 存在瓶颈,导致写出缓慢,阻塞数据库正常运行 
4. 由于数据文件磁盘 I/O 瓶颈,DBWR 写出过于缓慢
5. 由于事务量具大,DBWR 负荷过高,不堪重负
针对不同的原因,我们可以从不同角度着手解决问题:
1. 适当增加日志文件大小
2. 适当增加日志组数 
3.使用更快速磁盘存储日志文件(如采用更高转速磁盘;使用 Raid10 而不是Raid5 等方式)
4. 改善磁盘 I/O 性能
5. 使用多个 DBWR 进程或使用异步 I/O 等


INACTIVE 状态的日志也可能没有被归档。


UNUSED指该日志从未被写入,这类日志可能是刚被添加到数据库或者在 RESETLOGS 之后被重 置。被使用之后,该状态会被改变。


日志大小
select max(lebsz) from x$kccle;


在 Linux/Unix 下,Oracle 还 供另外一个命令行工具可以用于检查文件的 block size 大小:
[oracle@jumper conner]$ dbfsize redo01.log 
Database file: redo01.log
Database file type: file system
Database file size: 20480 512 byte blocks 
[oracle@jumper conner]$ dbfsize system01.dbf 
Database file: system01.dbf
Database file type: file system
Database file size: 51200 8192 byte blocks


指定归档
SQL> select * from v$log;--查看sequence
SQL> alter system archive log sequence 80;


所以我们建议,在备份时(特别是繁忙的数据库),应该尽量采用 RMAN 备份。由于 Rman 可以通过反复读取获 得一致的 Blok,从而可以避免 SPLIT Block 的生成,所以不会产生额外的 REDO。


如果数据库丢失的是非活动(INACTIVE)日志组,由于非活动日志组已经完成检查 点,数据库不会发生数据损失,此时只需要通过 Clear 重建该日志组即可恢复。
alter database clear logfile group 2;
注意,如果数据库处于归档模式下,并且该日志组未完成归档则需要使用如下命令强制清除
alter database clear unarchived logfile group 2;


很多数据库是从不备份的,那么在面对这种情况时,Oracle  供给我们一 种内部手段可以用于强制性数据库打开,忽略一致性等问题,在打开数据库之后,Oracle 建议 导出(exp)数据,然后重建数据库,再导入(imp)数据,完成灾难恢复。


_ALLOW_RESETLOGS_CORRUPTION该参数的含义是,允许在破坏一致性的情况下强制重置日志,打开数据库。 _ALLOW_RESETLOGS_CORRUPTION 将使用所有数据文件最旧的 SCN 打开数据库,所以通 常需要保证 SYSTEM 表空间拥有最旧的 SCN。


如果日志都处于 active 状态,那么显然 DBWR 的写已经无法跟上 Log Switch 触发的检查 点。









































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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值