分类:
2012-03-31 20:13:11
原文地址:Oracle DBWn(DBWR)写数据文件 作者:EnchanterBlue
首先介绍下DBWn(和DBWR是一个概念,DBWR就是database writer,就是写数据文件的进程, 后来允许多进程写data file,所以改成DBWn了):
DBWn:数据块写进程,负责将Oracle数据库缓冲区的脏缓冲写到数据文件内(脏缓冲是已经被修改,但未写入数据文件的数据)为了保证缓冲区能有空余缓冲供用户使用
DBWn会根据LRU(最近最少使用)算法找出相应的脏缓冲,并将其写入数据文件,初始参数DB_WRITER_PROCESSES,可以设定Oracle的DBWn进程个数(最大20)
DBWn在将脏缓冲写入的时候,一次可以写入多个数据块的数据
DBWn触发的条件:
1、当dirty list达到一定数量(阀值25%),,导致Server Proceess通知DBWn写赃数据
2、当扫描LRU list达到一定数量还未找到free buffer 时,停止搜索free buffer,直接通知DBWn写脏数据
3、checkpoint写数据
通常数据的访问和修改都是需要通过buffer cache来完成的,当一个server process访问数据的时候,首先需要确定的是,我们所需要的数据在buffer cache是否存在,如果存在我们还需要根据data buffer的状态来判断是否进行db block gets 还是consistent gets,如果不存在,则我们需要在buffer cache中寻找足够的空间来加载我们所需要的数据,如果在buffer cache中我们找不到足够的空闲空间(free buffer),那么我就需要触发DBWn进程去写出脏数据,用来释放我们的buffer空间。
Oracle通过3个list来对buffer进行管理,是LRU List + Dirty List+Auxiliary List
这些list存放的就是具体指向buffer的指针,类似索引。
LRU List主要就是用来维护内存中的buffer,按照我们LRU(Least Recently
Used)的方式来进行管理.,当db初始化的时候,所有的buffer都被捕HASH到LRU
List上进行管理.当我们从数据文件中读取数据的时候我们现在要在LRU
List上面寻找free的buffer,然后将数据读取到我们所找到的这个free
buffer中.只要数据被修改了,那么这个buffer的状态就变为了dirty,那么Oracle就会把这个buffer从LRU
List移到Dirty
List(Checkpoint Queue)中去.在Dirty
List上的buffer都是一些候选的稍后会被DBWn写出到数据文件的buffer, 注意点:一个buffer要么存在于LRU
List上面,要么存在于Dirty List上面,不可能同时存在于两个List上面。
a、.当Server process试图通过扫描LRU
List来寻找Free的Buffer的时候,扫描过程中会把已发现的所有Dirty buffer从LRU List移动到Dirty
List(Checkpoint Queue)中去,同时,这些buffer是我刚才说的可以候选的被DBWn进程写出到数据文件中的buffer.
(Server process主动将Dirty buffer从LRU List移动到Dirty List) --移动
b、当Dirty List(Checkpoing Queue)中的Dirty Buffer量超过了一定的阀值,那么Server process就会通知DBWn进程写出脏数据
(Checkpoint Queue阀值到达25%,,导致Server Proceess通知DBWn写赃数据) --写
c、如果Server
process扫描了LRU超过一个阀值也没有找到足够的Free的buffer,这个时候也将会停止搜索free
buffer的任务然后直接通知DBWn写脏数据来释放内存空间,当然这个Server process会处于free busy
wait的等待事件.这个阀值是40%,同时这还是触发我们DBWn进程的一个条件
(LRU扫描40%没有找到Free buffer,Server process通知DBWn写脏数据) --写
d、从Oracle 8i开始呢LRU List和Dirty List分别又引入了Auxiliary
List,目的是为了提高管理的效率.那么这个List的是怎么工作的呢?当我们的数据库初始化的时候,BUffer首先会被HASH到LRU的
Auxiliary List(Auxiliary
RPL_LST)上面,那么当buffer被使用后(注意:是使用而不是修改),会被从LRU的Auxililary List移动到LRU的Main
List(MAIN RPL_LST)上面,这个时候当用户搜索Free
buffer的时候,就可以从Auxiliary RPL_LST中开始,而DBWn主动搜索LRU List寻找Dirty
buffer的时候就会从MAIN RPL_LST开始.这样一来就提高了我们数据库的搜索效率和性能。
DBWn如何写数据文件:
在 写数据文件前首先要找到可写的空闲数据块,oracle中空闲数据块可以通过freelist或bitmap(10g都是位图维护)来维护,它们位于一个 段的头部用来标识当前段中哪些数据块可以进行insert。在本地管理表空间中oracle自动管理分配给段的区的大小,区的分配信息存储在组成表空间的 数据文件的头部,而数据字典管理的表空间用户可以在创建时决定区的大小,并且区的分配信息是存储在数据字典中的,只在本地管理的表空间中才能选用段自动管 理,采用自动段空间管理的本地管理表空间中的段中的空闲数据块的信息就存放在段的头部且使用位图来管理,采用手动管理的本地管理表空间中的段和数据字典管 理的表空间中的段中的空闲数据块的管理都使用段头部的空闲列表来管理。
空闲列表的工作方式:首先一个空的数据块被加入空闲列表,当其中空闲空间小于pctfree设置的值后,这个块从空闲列表删除,当这个块中的内容降至 pctused设置的值之下后,这个数据块被再次加入空闲列表,位于空闲列表中的数据块都是可以向其中insert的,当一个块移出了空闲列表,但只要其 中还有保留空间就可以进行update,当对其中的一行update一个大数据时,如果当前块不能完全放下整个行,只会把整个行迁移到一个新的数据块,并 在原块位置留下一个指向新块得指针,这叫行迁移。如果一个块可以insert,当出入一个当前块装不下的行时,这个行会溢出到两个或两个以上的块中,这叫行链接。(行链接比较常见,但要尽量避免行迁移,这是影响性能的一个重要因素)
如果用户的动作是insert则服务器进程会先锁定freelist,然后找到空闲块得地址,再释放freelist,当多个服务器进程同时想要锁定 freelist时即发生freelist的争用,可以在非采用自动段空间管理的表空间中创建表时指定freelist的个数,默认为1,如果是在采用自 动段空间管理的表空间中创建表,即使指定了freelist也会被忽略,因为此时将使用bitmap而不是freelist来管理段中的空闲空间。
如果用户动作是update则服务器进程将不会使用到freelist和biemap,因为不要去寻找一个空闲块,而使用锁的队列。