2007年6月26日星期二

《Expert one on one Oracle》- 重做回滚- 笔记-2

块清除

当Oracle更改数据块时,会对这个数据块进行跟踪。在提交的时候,将会重新访问这个块并将更改标记为已经提交。但是只标示那些还没有从db_block_buffers中清除的块。而且,如果更改了太多的块,那么也只有前面少数的块(db_block_buffers的10%)被重新访问。

当提交的时候,如果这些块还在缓存中,那么Oracle将会进行fast commit,清除块头部的事务信息。对于那些已经从db_block_buffers中清除,被写入磁盘的数据块,Oracle将会忽略这些块。当下次的DML或者查询语句再访问这些块的时候,由这些语句负责清除,这就是所谓的delayed block cleanout。所以,即使是查询语句也可能产生重做日志。

通过如下的方法来验证:
a. 创建表,保证一块只能存储一行,在8K大小数据块中,创建每行大小为6K的数据库;
b. 插入499行纪录,使用499个数据块,其大小已经超过30(也即300的10%);
c. 提交;
d. 对于在db_block_buffers的数据块(同时保证小于db_block_buffers 10%),Oracle执行fast commit,对于其他的数据块Oracle将忽略;
e. 执行全表扫描的查询语句。这条语句将会重新访问步骤d中没有被清除的块,对这些块头的事务信息进行清除,这个步骤将会产生重做日志。
f. 检查通过步骤e查询所产生的重做日志。
g. 执行新的查询,由于步骤e已经清除块头的事务信息,这个时候查询将不会需要清除块,也不会产生重做日志。

SQL> create table t --保证一块只能存储一行
2 ( x char(2000) default 'x',
3 y char(2000) default 'y',
4 z char(2000) default 'z' )
5 /

Table created.

SQL>
SQL> insert into t --插入499行纪录,使用499个数据块
2 select 'x','y','z'
3 from all_objects where rownum <500
SQL> commit;-- 提交,插入过程中部分快会执行fast commit,部分块被忽略

Commit complete.

SQL>
SQL> column value new_value old_value
SQL>
SQL> select * from redo_size;

VALUE
----------
3332424

SQL>
SQL> select *
2 from t
3 where x = y;

no rows selected

SQL> select value-&old_value REDO_GENERATED from redo_size;
old 1: select value-&old_value REDO_GENERATED from redo_size
new 1: select value- 3332424 REDO_GENERATED from redo_size

REDO_GENERATED
--------------
10740 --查询过程产生了重做日志,证明进行了块清除操作

SQL> commit;

Commit complete.

SQL>
SQL> select value from redo_size;

VALUE
----------
3343164

SQL>
SQL> select *
2 from t
3 where x = y;

no rows selected

SQL>
SQL> select value-&old_value REDO_GENERATED from redo_size;
old 1: select value-&old_value REDO_GENERATED from redo_size
new 1: select value- 3343164 REDO_GENERATED from redo_size

REDO_GENERATED
--------------
0--查询过程没有产生重做日志,前面的查询已经清除块,第二次查询不再有清除动作


上面的第一个查询产生了重做日志,有可能促使这些块被DBWR重写。Oracle必须采用delayed clear out的策略,否则在提交的时候必须重新访问更新块,还可能从磁盘中读取快,这将会是相当耗时的工作。

有些事务创建“干净的”数据块,例如:CREATE TABLE AS SELECT。

在某些情况下,进行大量的数据更新之后,也可以主动访问数据块,让最终用户访问的时候速度会更快。例如通过ANALYZE命令,可以清除块。

参考:
Block cleanout - fast or delayed.

没有评论: