log添加 oracle redo_REDO扩展 – REDO与OWI

316c32e223d88cdc9c453b3b3100a537.png

REDO扩展 – REDO与OWI
我觉得这节的内容是最重要的,前面学习诸多REDO的理论,其实就是为了快速理解REDO相关OWI的原理,知道产生原因以至于快速拿出解决方案。
OWI,Oracle Wait Interface,指的是记录和观察集成所经历的等待现象的功能和界面及方法论。OWI是优化里非常重要的一项,里面内容也非常丰富。
我这里讨论的是和REDO相关的OWI,可能不是非常全面,但平常最容易看到的、也是最重要的内容是都会涉及的。
友情提示:想要更好理解本节内容,需要有lock和latch的基础。1、几个latch相关事件latch: redo allocation
sys@L10GR204> select name, gets, misses, immediate_gets, immediate_misses from v$latch_children where name = 'redo allocation';
NAME GETS MISSES IMMEDIATE_GETS IMMEDIATE_MISSES
------------------------------ ---------- ---------- -------------- ----------------
redo allocation 12148 8 90732 8
redo allocation 8222 0 3509 0
redo allocation 4811 0 0 0
redo allocation 645 0 0 0
redo allocation 289 0 0 0
redo allocation 1645 0 0 0
redo allocation 291 0 0 0
redo allocation 89 0 0 0
redo allocation 387 0 0 0
redo allocation 287 0 0 0
redo allocation 33 0 0 0
redo allocation 373 0 0 0
redo allocation 2119 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
redo allocation 5 0 0 0
20 rows selected.
如果在获取redo allocation latch的过程中发生争用,将会产生latch: redo allocation等待事件。latch: redo writing
为了占有Log Buffer里的空间,向LGWR请求写入工作的进程需要获得redo writing latch。
sys@L10GR204> select name, gets, misses, immediate_gets, immediate_misses from v$latch_parent where name = 'redo writing';
NAME GETS MISSES IMMEDIATE_GETS IMMEDIATE_MISSES
------------------------------ ---------- ---------- -------------- ----------------
redo writing 29204 0 0 0
redo writing latch是独立的,从v$latch_parent中只能看到一个,而且它是以willing-to-wait方式获取的。
如果获取这过程中发生争用,就会等待latch: redo writing事件。latch: redo copy
Redo CV存到Log Buffer整个过程中,还需要拥有redo copy latch,它的数量取决于隐含参数_LOG_SIMULTANEOUS_COPIES的值,我的当前系统中是8.
sys@L10GR204> @GetHparDes
Enter value for par: simultaneous
old 6: AND x.ksppinm LIKE '%&par%'
new 6: AND x.ksppinm LIKE '%simultaneous%'
NAME VALUE DESCRIB
------------------------------ -------------------- --------------------------------------------------------------------------------
_log_simultaneous_copies 8 number of simultaneous copies into redo buffer(# of copy latches)
sys@L10GR204> select name, gets, misses, immediate_gets, immediate_misses from v$latch_children where name = 'redo copy';
NAME GETS MISSES IMMEDIATE_GETS IMMEDIATE_MISSES
------------------------------ ---------- ---------- -------------- ----------------
redo copy 9 0 36289 69
redo copy 9 0 60313 22
redo copy 9 0 0 0
redo copy 9 0 0 0
redo copy 9 0 0 0
redo copy 9 0 0 0
redo copy 9 0 0 0
redo copy 9 0 0 0
8 rows selected.
redo copy latch是有可能以no-wait模式获取,也有可能以willing-to-wait模式获取,在这获取过程中如果发生争用,就会等待latch: redo copy事件。
这三个latch不会深入说明,想要更深入的话,请查阅相关资料。
下面我们将上面三种latch争用统一看成一个,那都有什么可能会造成这些latch争用。

  • Log Buffer大小
  • 应用产生大量redo


首先看Log Buffer大小,如果Log Buffer不够大,LGWR将会频繁的工作,把日志写入到REDO LOG FILE里。这种频繁的操作将会增加latch的争用。
下面看一个示例:
column EVENT for a65
select *
from (
select event, total_waits, time_waited
from v$system_event
where wait_class <> 'Idle'
order by 3 desc
)
where event like 'latch%'
/
[oracle@khm21 ~]$ cat show_mysess.sql
column event for a60
select
event,
total_waits,
time_waited
from v$session_event
where
sid = (select sid from v$mystat where rownum=1)
order by 3 desc
/
我先把日志调整到1M大小,但重启之后发现有趣的事情
sys@L10GR204> alter system set log_buffer=1048576 scope=spfile;
sys@L10GR204> startup force -- 请慎用
sys@L10GR204> show parameter log_buffer
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
log_buffer integer 2044928
– 这里可见log buffer并不是我设置的1M,这是因为Oracle 10g 动态分配SGA之后,SGA各部分调整是根据granule进行分配的。所以,尽管我设置1048576,这里重启后自动修改为2044928了。
我这里已经有一张16W数据的表
luocs@L10GR204> select count(*) from ltb;
COUNT(*)
----------
163400
创建一个过程,对ltb表进行delete,然后马上回滚:
create or replace procedure ltb_update
is
begin
for i in 1 .. 10000 loop
execute immediate 'update ltb set owner='||chr(39)||'LUOCS'||chr(39)||' where object_id=' ||i;
commit;
end loop;
end;
/
打开20个会话并执行该存储过程
var jobno number;
begin
for l in 1 .. 20 loop
dbms_job.submit(:jobno, 'ltb_update;');
commit;
end loop;
end;
/
luocs@L10GR204> @show_mysess
EVENT TOTAL_WAITS TIME_WAITED
------------------------------------------------------------ ----------- -----------
SQL*Net message from client 199 142176
db file sequential read 472 5258
log buffer space 17 296
db file scattered read 7 151
log file sync 9 48
latch: library cache 2 17
log file switch (checkpoint incomplete) 2 17
log file switch completion 2 6
SQL*Net message to client 200 0
-- 看到了一些和Log相关的等待,log开头的等待如经典的log file sync在后面说明。
sys@L10GR204> @showsysevent
EVENT TOTAL_WAITS TIME_WAITED
----------------------------------------------------------------- ----------- -----------
latch: cache buffers chains 25069 348514
latch: undo global data 1247 25684
latch: cache buffers lru chain 926 8794
latch: enqueue hash chains 28 2051
latch free 132 1442
latch: shared pool 26 234
latch: redo allocation 85 207
latch: cache buffer handles 12 204
latch: library cache 22 168
latch: In memory undo latch 4 46
latch: row cache objects 1 7
latch: object queue header operation 10 1
latch: checkpoint queue latch 3 0
latch: session allocation 2 0
latch: messages 2 0
15 rows selected.
-- 这里能看到latch: redo allocation事件。
从上面数据显示,尽管能看到和redo相关的latch等待和其他等待,但它们所占比例并不很大。
应用产生大量REDO,这个时候我们需要分析这些REDO是不是必须要产生的,如果是不必要的,我们应该采用Oracle提供的最小化REDO的方法,如下:
1)使用Nologging;
2)DIRECT PATH INSERT
3)SQL*Loader(实际上是DIRECT PATH INSERT的一种)
4)使用临时表
5)在DIRECT LOAD时,如果有索引,需要先把索引改成unusable状态,产生数据之后,使用Nologging重建。2、log file parallel write
这是一种很容易看到的等待事件,下面就是从AWR里看到的。

87969e8a081356c541faf2c712777d33.png


从上面可以看见log file parallel write是属于system I/O类的。
我们都知道lgwr这个后台进程是将REDO从Log Buffer写入到日志文件里的,lgwr为了完成这项工作,执行必要的I/O调用,在等待I/O工作完成期间将等待log file parallel write事件。
sys@L10GR204> select PARAMETER1, PARAMETER2, PARAMETER3 from v$event_name where name='log file parallel write';
PARAMETER1 PARAMETER2 PARAMETER3
--------------- --------------- ---------------
files blocks requests
log file parallel write等待大多和I/O性能有关,但假如忽略I/O性能,那么就可以怀疑REDO的量了。
那如何解决log file parallel write等待(提高lgwr的性能),我们可以从下面几个方向去考虑:
1)减少commit;
2)使用Nologging,以减少redo量
3)提高存放日志文件的存储I/O
4)不要在高并发的时候频繁执行热备份(Hot Backup),因为热备份将会产生块级别的REDO3、log buffer space
在上面做实验的时候,我们看到过log buffer space等待。另外,在最前面也提过redo allocation latch。
在获得了redo allocation latch之后,想要从Log Buffer里获得空间存放REDO CV,如果日志文件已满需要切换,这时候会等待log buffer space事件,当然后还会等待后面要说的log file switch completion事件。其实,log buffer space常发生于REDO量太大以至于Log Buffer显得小的时候。
常伴随着出现的就是log file switch completion等待事件。
下面我做简单的测试,还是针对上面的那张ltb表,做如下事情:
1)在log buffer当前1M大小下delete这张表数据库,然后rollback,观察Log相关等待
2)调整log buffer为10M,再delete表数据,然后rollback,观察Log相关等待
TEST 1:
luocs@L10GR204> delete from ltb;
luocs@L10GR204> rollback;
luocs@L10GR204> @show_mysess
EVENT TOTAL_WAITS TIME_WAITED
------------------------------------------------------------ ----------- -----------
SQL*Net message from client 31 5273
log buffer space 97 587
db file sequential read 132 47
log file switch completion 7 19
db file scattered read 307 2
log file sync 1 2
SQL*Net message to client 32 0
7 rows selected.
TEST 2:
修改log buffer大小
sys@L10GR204> alter system set log_buffer=10485760 scope=spfile;
sys@L10GR204> startup force
sys@L10GR204> show parameter log_buffer
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
log_buffer integer 14246912
luocs@L10GR204> delete from ltb;
luocs@L10GR204> rollback;
luocs@L10GR204> @show_mysess
EVENT TOTAL_WAITS TIME_WAITED
------------------------------------------------------------ ----------- -----------
SQL*Net message from client 25 1239
log buffer space 9 308
log file switch completion 5 15
log file sync 2 12
db file scattered read 308 2
events in waitclass Other 62 1
SQL*Net message to client 26 0
db file sequential read 149 0
8 rows selected.
在我们加大Log Buffer之后,log buffer space确实减少了,但加大Log Buffer可能会增加log fyle sync事件。log file sync是我们重点讨论对象,我将放在最后说明。4、log file switch completion
这个等待上面已经提过,服务器进程写入日志时发现日志文件已满,便请求lgwr切换日志,在lgwr切换日志结束之前,服务器进程将会等待,这时候发生log file switch completion等待事件。5、log file switch (checkpoint incomplete)
上面lgwr切换日志结束后,发现要使用的新日志文件还没完成检查点,进程就要等待DBWn进程结束检查点,这时候进程等待log file switch (checkpoint incomplete)事件。6、log file switch (archiving needed)
上面lgwr切换日志结束后,发现要使用新日志文件还没完成归档,进程就要等待ARCH进程结束归档,这时候进程等待log file switch (archiving needed)事件。7、log file sync
这是和redo相关的最经典等待事件之一,再回顾下面AWR报告中TOP 5等待事件部分:

87969e8a081356c541faf2c712777d33.png


我们发现log file sync是commit类型的等待,那下面说明log file sync如何产生的。
我们回顾一下commit机制:

  • 在commit之前,DML已经在SGA中产生了UNDO块儿
  • 在commit之前,已经在SGA中产生了已修改的数据块儿
  • 在commit之前,redo log buffer中已经产生了上面两项的redo
  • 根据lgwr将redo从redo log buffer写到磁盘的机制,比如工作时间,有可能将部分redo数据写入磁盘
  • 已经获得了所需全部锁
  • 在commit当时,为事务生成一个SCN
  • lgwr将剩余的redo写入磁盘,并且把SCN标记到current redo log file里。
  • 到这里事务提交结束,该事务从v$transaction里消失
  • 释放锁


这里再加上rollback机制:

  • 在rollback之前,DML已经在SGA中产生了UNDO块儿
  • 在rollback之前,已经在SGA中产生了已修改的数据块儿
  • 在rollback之前,redo log buffer中已经产生了上面两项的redo
  • 根据lgwr将redo从redo log buffer写到磁盘的机制,比如工作时间,有可能将部分redo数据写入磁盘
  • 已经获得了所需全部锁 — 直到这里,commit和rollback之前做的工作都是一样的
  • 撤销所有已修改的工作,过程是先从undo段读回数据,逆向执行前面所做的操作,并将undo条目标记为已用
  • 释放所


服务器进程执行commit或rollback之后,LGWR进程将Log Buffer里的REDO写入到日志文件,一直到写入结束,commit或rollback完成,在这个过程中等待log file sync事件。
有人想完全去除log file sync,但这是不太现实的事情,因为只要事务存在就需要commit或者rollback,因此系统里存在log file sync等待是非常正常的。
但log file sync要是大量出现,那这个是非正常的现象,DBA需要优化,可以从下面几个方面思考:
1)减少commit次数(批量提交或异步提交);
2)减少REDO量;
3)加大Log Buffer;
4)提高存储I/O效率
这里看下第四项,在上面也提到过,其实这是属于REDO LOG FILE的优化层面了。
那我们讨论如何优化联机日志文件:
仔细想想Oracle体系结构研究过程中关于日志文件Oracle是如何建议的:多组、多成员、多元化。
更深入了解的话:
1)日志组的数量要足够多;
2)日志成员镜像化;
3)日志成员大小要足够大;
4)日志文件存储的性能要好。
当然,这里没有满足大部分系统的恒定值,要根据自己系统情况而改变。
另外,从系统角度去看的话DBA可能需要关注日志切换的时间,我们经常听到20分钟一说,也就是保证系统的日志切换时间在20分钟左右。当然,这是一个比较优秀的切换时间,但一个高并发的大型系统中,想要满足这个值确实不是简单的事情,因此,这个20分钟也不是恒定的。DBA只要保证,日志的切换不会给系统带来严重的性能影响,那日志切换时间减少到10分钟或者更低也是可以接受的。
这里关于提高存储I/O效率简单说下。
LGWR进程往日志文件里写REDO的时候是顺序写的,它无法使用并行技术来提高写得效率,这个和REDO保证数据安全恢复的机制有关。因此,DBA需要考虑将日志文件存放在快速设备上,比如使用RAID 1+0技术的设备(不建议存放在采用RAID 5技术的设备上)。然后日志组和成员以及归档日志存放也是有技巧的。
下面是比较优秀的日志文件分布方案:
假如联机日志组有6个,每组有2个成员,并且存储已做好4个RAID10组和1个RAID5组。

  • G1 ~ G6表示联机日志组名,G1 : member1表示组1第一个成员;
  • 日志成员都存放于RAID10组(或者节省成本RAID0);
  • 归档日志存放于RAID5组;
  • G1:member1放到磁盘组1、G1:member2放到磁盘组2;
  • G2:member1放到磁盘组3、G2:member2放到磁盘组4;
  • G3:member1放到磁盘组1、G3:member2放到磁盘组2;
  • G4:member1放到磁盘组3、G4:member2放到磁盘组4;
  • G5:member1放到磁盘组1、G5:member2放到磁盘组2;
  • G6:member1放到磁盘组3、G2:member6放到磁盘组4;

下面是直观分布图:

87969e8a081356c541faf2c712777d33.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值