3、延伸思考
在高并发,多用户的数据库系统中,所有客户端进程都是通过向redo log buffer写入重做数据来确保数据的完整与一致性。对于redo log buffer的管理,则通过latch的机制来实现。和redo相关的latch主要有两个,一个是redo allocation latch,一个是redo copy latch。前者负责将为新的redo在redo log buffer中分配空间,后者则是pga中的redo复制到redo log buffer。下面是描述一下redo产生的流程。
用户进程产生redo(位于PGA中)====>服务器进程获取Redo Copy latch(存在多个取决于CPU_COUNT*2)====>服务进程获取redo allocation latch(仅1个)====>分配log buffer====>释放redo allocation latch====>将Redo Entry写入Log Buffer====>释放Redo Copy latch
如前文Doc ID 372557.1所述,Oracle 9.2之后引入了log_parallelism机制,当该参数的值大于1的时候,数据库会分配多个共享的redo log buffer,也就是说redo log buffer被再次细分,使得每个共享的buffer使用独立的redo allocation latch来进行保护以提高redo的并发性。这些个共享的redo log buffer就被称之为 shared strand。在10gR2以后了又多出了一个private strand,这个东东是从shared pool中分配而不是先前的log buffer。private strand为大量小的私有内存,通常每个大小在64kb-128kb左右,被独立的redo allocation latch所保护。每个特定的小事务会绑定到独立且空闲的private redolog strand,即绑定到一个活动事务。在这种新机制引入后,一旦用户进程申请到private strand,redo不再保存的pga中,因此不再需要redo copy latch这个过程。如果新事务申请不到private strand的redo allocation latch,则会继续遵循旧的redo buffer机制,申请写入shared strand中。由于新机制的引入,相应的redo的产生发生了一些变化,如下:
新事务开始====>申请private strand的redo allocation latch(申请失败则申请shared strand的redo allocation latch)====>在private strand中生产redo Entry====>flush/commit====>申请redo copy latch====>LGWR将redo entry批量写入log File====>释放redo copy latch====>释放Private strand的redo allocation latch
对于这个新的机制,在进行redo被写出到logfile时,LGWR需要将shared strand与private strand的内容写出。当redo flush发生时,所有的publicredo allocation latch需要被获取,所有的public strands的redo copy latch需要被检查,所有包含活动事务的private strands需要被持有。
由上可知,Private strand flush not complete事件的出现是通过增加参数DBWn的值来避免。因为DBWn会触发LGWR将redo写入到logfile。