1、概述
在10g中,redolog
buffer的改进,的确是个不小的创新,我最近研究了下10g版本在redolog buffer上的改进,和大家共享下。
说之前,我先提下,redo信息产生的过程:
1)先在PGA区域中生成redo entries,也就是redo条目,并计算大小记录之;
2)服务器进程oracle<sid>去rodolog
buffer中申请 redo copy latch(redo 复制闩),失败了,会发生等待事件,成功了则:
3)再去申请redo allocation latch(在rodolog buffer中申请空间的闩),一旦redo中有足够的空间,就可以申请成功,这时
4)释放这个redo allocation latch
5)服务器进程再去申请redo writting latch(redo 写入内存的闩),成功后则:
6)服务器进程把PGA中准备好得redo entries 写入到redolog buffer中,
7)按顺序释放redo writting latch 和redo copy latch。
分析以上7步,完成redo信息的产生,接下来就是lgwr进程的写入在线日志文件的工作了,我不去介绍。
大家观测这个过程不难发现,redo copy latch在开始就被申请,而最后才被释放,势必会引起争用,或者等待事件的发生,降低了效率,到了9i这个版本,oracle引入了PBRS(public
redo strands)机制,就是借鉴了share pool 分出多个子池(subpool)的思想,也分出了多个log buffer,每个buffer有独立的latch保护,以提高并发性,提高效率。
到了10g版本,又有了改革的新思想,就是PVRS(private redo strands)机制。原理是,在share pool中申请多个小的私有内存空间,每个在64-128KB之间,被独立的redo allocation latch保护。这样的好处是显而易见的,单个redo信息很小,但个数很多的时候(oracle多年测试得出结论就是大多数事务所产生的redo都是很小的,但次数比较多),不会在PGA中产生redo
entries,而是直接放在 share pool中申请多个小的私有内存空间中,redo copy latch也不再需要,因为oracle认为redo copy latchF这个闩是是引发竞争的根源。当redo写出到文件时,LGWR将PBRS和PVRS中的内容写出到日志文件中。产生日志时首选pvrs,如果redo条目太大,或者share pool没有空间,再用redo log buffer(也就是9i时发明的PBRS中)。
2、Oracle 10g InMemory Undo新特性
通过以前的介绍,可知道Undo的管理方式和常规的数据管理方式是相同的,当进行数据修改时,会在Buffer中创建前镜像,同时会记录相应的Redo,然后这些Undo数据同样会写出到UNDO SEGMENT上,当进行一致性读或回滚时,可能会产生大量的consistentgets和physical reads。注意到这里,Undo会产生Redo信息,又会写UNDO
SEGMENT,进而又可能产生大量读取I/O,这些都是资源密集型操作。如果能够缩减Undo在这些环节的Redo与Undo写出,那么显然就可以极大地提升数据库性能,减少资源的消耗和使用。
从Oracle10g开始,Oracle在数据库中引入了In Memory Undo(可以被缩写为IMU)的新技术,使用这一技术,数据库会在共享内存中(Shared Pool)开辟独立的内存区域用于存储Undo信息,这样就可以避免Undo信息以前在Buffer Cache中的读写操作,从而可以进一步的减少Redo生成,同时可以大大减少以前的UNDO
SEGMENT的操作。IMU中数据通过暂存、整理与收缩之后也可以写出到回滚段,这样的写出提供了有序、批量写的性能提升。
IMU机制与前面日志提到的PVRS紧密相关,由于每个IMU Buffer的大小在64~128KB左右,所以仅有特定的小事务可以使用,每个事务会被绑定到一个独立的空闲的IMU Buffer,同时相关的Redo信息会写入PVRS中,同样每个IMU Buffer会由一个独立的In Memory Undo Latch保护,当IMU Buffer或PVRS写满之后,数据库需要写出IMU中的信息。
一个新引入的隐含参数可以控制该特性是否启用,这个参数是_in_memory_undo,在Oracle 10g中这个参数的缺省值是TRUE(不同版本和平台参数的初始设置可能不同):
sys@TQGZS> @GetHidPar.sql
Enter value for par: _in_memory_undo
old 4: AND x.ksppinm LIKE '%&par%'
new 4: AND x.ksppinm LIKE '%_in_memory_undo%'
NAME VALUE DESCRIB
------------------------------ ---------------------- ----------------------------------------------------------
_in_memory_undo TRUE Make in memory undo for top level transactions
IMU的内存在Shared Pool中分配,回想一下Redo Log Buffer的内存使用与功能,实际上IMU技术在某种程度上也是参考了Log Buffer的机制,通过以下查询可以获得系统当前分配的IMU内存:
sys@TQGZS> select * from v$sgastat where name ='KTI-UNDO';
POOL NAME BYTES
------------ ------------------------------ ----------
shared pool KTI-UNDO 1235304
In Memory Undo池缺省的会分配3个,用以提供更好的并发:
sys@TQGZS> @GetHidPar.sql
Enter value for par: _imu_pool
old 4: AND x.ksppinm LIKE '%&par%'
new 4: AND x.ksppinm LIKE '%_imu_pool%'
NAME VALUE DESCRIB
----------------------- ------------------ ------------------------------------------------
_imu_pools 3 in memory undo pools
IMU的使用信息,如提交次数可以通过V$SYSSTAT视图查询:
sys@TQGZS> select name,value from v$sysstat where name like '%commits';
NAME VALUE
------------------------------ -------------
usercommits 2877
IMUcommits 1549
新的内存Buffer通过In Memory Undo Latch来进行保护:
sys@TQGZS> select name,gets,misses,immediate_gets,sleeps
from v$latch_children where name like '%undo latch';
NAME GETS MISSES IMMEDIATE_GETS SLEEPS
------------------------------ ---------- ---------- -------------- ----------
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undo latch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 0 0 0 0
In memory undolatch 4 0 2 0
In memory undolatch 214 0 25 0
In memory undolatch 6118 0 3064 0
In memory undolatch 4230 0 1084 0
In memory undolatch 39583 0 2842 0
18 rows selected.
除了前面提到的,还有几个隐含参数与IMU有关:
·_recursive_imu_transactions:控制递归事务是否使用IMU,该参数缺省值为False;
sys@TQGZS> @GetHidPar.sql
Enter value for par: _recursive_imu_transactions
old 4: AND x.ksppinm LIKE '%&par%'
new 4: AND x.ksppinm LIKE '%_recursive_imu_transactions%'
NAME VALUE DESCRIB
------------------------------ --------------------- ---------------------------------------------
_recursive_imu_transactions FALSE recursive transactions may be IMU
·_db_writer_flush_imu:控制是否允许DBWR将IMU事务的降级为常规事务,并执行UNDO SEGMENT的写出操作,缺省值为TRUE。
sys@TQGZS> @GetHidPar.sql
Enter value for par: _db_writer_flush_imu
old 4: AND x.ksppinm LIKE '%&par%'
new 4: AND x.ksppinm LIKE '%_db_writer_flush_imu%'
NAME VALUE DESCRIB
------------------------------ --------------------------------------------------------------------------------
_db_writer_flush_imu TRUE If FALSE, DBWR will not downgrade IMU txns for AGING
此外,在RAC环境中,IMU不被支持。
经过不同版本Oracle技术的不断演进,Oracle的内存管理已经和以前大为不同,现在Buffer Cache、Shared Pool、Log Buffer的内容正在不断交换渗透,Redo、Undo数据都可以部分地存储在共享池中,Oracle 11g的Result Cache也被记录在Shared
Pool当中。
- The End -