在介绍buffer cache的时候,说到DBWR进程会将脏数据写入到数据文件,这里我们来看一下DBWR进程的简单概念,oracle现在有一大堆进程,DBWR就是其中一个非常重要的进程,在如今的系统中,一个DBWR进程显然已经满足不了现在的需求,特别是大数据时代的降临,我们可以为系统配置多的DBWR进程,此参数由db_writer_processes进程决定
1 2 3 4 5 6 |
SQL> show parameter db_writer_processes NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_writer_processes integer 1 SQL> |
DBWR进程是一个后台进程,当满足一定的条件之后,此进程会被触发:
1) 当进程在辅助LRU链表和主LRU链表上扫描以查找可以覆盖的buffer header时,如果已经扫描的buffer header的数量到达一定的限度(由隐藏参数:_db_block_max_scan_pct决定)时,触发DBWR进程。_db_block_max_scan_pct表示已经扫描的buffer header的个数占整个LRU链表上buffer header总数的百分比。这时,搜索可用buffer header的进程挂起,在v$session_wait中表现为等待“free buffer wait”事件,同时增加v$sysstat中的“dirty buffers inspected”的值。
2) 当DBWR在主LRUW链表上查找已经更新完而正在等待被写入数据文件的buffer header时,如果找到的buffer header的数量超过一定限度(由隐藏参数:_db_writer_scan_depth_pct决定)时,DBWR就不再继续往下扫描了,而转到辅助LRUW链表上将其上的脏数据块写入数据文件。_db_writer_scan_depth_pct表示已经扫描的脏数据块的个数占整个主LRUW链表上buffer header总数的百分比。
3) 如果主LRUW链表和辅助LRUW链表上的脏数据块的总数超过一定限度,也将触发DBWR进程。该限度由隐藏参数:_db_large_dirty_queue决定。
4) 发生增量检查点(incremental checkpoint)或完全检查点(complete checkpoint)时触发DBWR。
5) 每隔三秒钟启动一次DBWR。
6) 将表空间设置为离线(offline)状态时触发DBWR。
7) 发出命令:alter tablespace … begin backup,从而将表空间设置为热备份状态时触发DBWR。
8) 将表空间设置为只读状态时,触发DBWR。
9) 删除对象时(比如删除某个表)会触发DBWR。
10)rac的ping时
当然当DBWR进程要写脏数据块时,也并不是立即将所有的脏数据块都同时写入磁盘,oracle为了尽量减少物理io的次数,DBWR会将需要写的脏数据块对应的buffer header拷贝到一个批量写(write batch)的结构中,当批量写里面的buffer header个数达到一定限额时,才会发生实际情况的io操作,将脏数据块写入到磁盘,这个限额是由oracle自己来计算的。
这篇文章先不讲DBWR是如何将脏数据块写入到数据文件的,我们先来看dbwr是否可以在事物提交之前写入数据文件?
1.创建一个测试表空间,一个测试用户,并将测试用户的默认表空间改为测试所用的表空间
1 2 3 4 5 6 7 8 9 10 11 |
SQL> create tablespace dbwrtest datafile '/opt/oracle/oradata/orcl/dbwrtest.dbf' size 10m; Tablespace created. SQL> create user dbwrtest identified by dbwrtest; User created. SQL> alter user dbwrtest default tablespace dbwrtest; User altered. |
2. 在测试用户下建立测试表,并插入一条记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
SQL> grant connect to dbwrtest; Grant succeeded. SQL> grant resource to dbwrtest; Grant succeeded. SQL> grant unlimited tablespace to dbwrtest; Grant succeeded. SQL> conn dbwrtest/dbwrtest; Connected. SQL> create table test(name varchar2(30)); Table created. SQL> insert into test values('jerry'); 1 row created. |
3. 此时新开一个窗口,用dba权限登陆,刷一下buffer cache
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
oracle@linux-fz9d:~> sqlplus / as sysdba SQL*Plus: Release 12.1.0.1.0 Production on Sun Jan 12 08:04:51 2014 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> alter system flush buffer_cache; System altered. |
4. 用操作系统strings命令查看第一条记录“jerry”是否已经插入到文件
1 2 |
oracle@linux-fz9d:~> strings /opt/oracle/oradata/orcl/dbwrtest.dbf |grep "jerry" jerry |
可以看出oracle已经将jerry写入到了数据文件中
5. 此时我们再向test表插入一条记录
1 2 3 |
SQL> insert into test values('xiao'); 1 row created. |
6.重复第4步操作,查看xiao是否在数据文件中
1 2 |
oracle@linux-fz9d:~> strings /opt/oracle/oradata/orcl/dbwrtest.dbf |grep "xiao" oracle@linux-fz9d:~> |
可以看出xiao这个字符没有写入到数据文件中,说明还停留在buffer cache中
7. 在另一个用户下新建一个辅助测试表,加强系统的繁忙程度,为了就是触发dbwr进程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SQL> create table test_aa as select * from dba_objects; Table created. SQL> insert into test_aa select * from test_aa; 91560 rows created. SQL> / 183120 rows created. SQL> / 366240 rows created. |
8. 此时重复第6步操作,查看xiao是否存在于数据文件中
1 2 |
oracle@linux-fz9d:~> strings /opt/oracle/oradata/orcl/dbwrtest.dbf |grep "xiao" xiao, |
这里可以清晰的看到xiao这个字符已经写入到了数据文件,但此时我事物还没有提交,只是DBWR进程被其他触发条件触发了,所以脏数据块就被写入到数据文件中了。从这个简单的实验就可以看出,在事物未提交之前,oracle是有可能将脏数据写入到数据文件的。
- 本文固定链接: http://www.savedba.com/?p=479
- 转载请注明: 版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!