并行读取时,采用的是direct read方式,这种方式不从buffer中读取,而是直接从磁盘上读取数据,而如果需要读取的数据在buffer中已经改变,是否会读取到错误的结果呢?
显然是不能读取到错误的结果的,oracle在执行并行读取前,需要对相应的segment发出检查点,把buffer中的脏数据写到磁盘中。
以修改表t_16k中的一行记录为例,首先查看buffer中该条记录所在的block相关信息:
SQL> select dbms_rowid.rowid_block_number(rowid) from cbo.t_16k where id=0;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
12
SQL> select object_id,object_name,owner,object_type from dba_objects where object_name='T_16K';
OBJECT_ID OBJECT_NAME OWNER OBJECT_TYPE
---------- ---------------------------------------- ------------------------------ -------------------
13780 T_16K CBO TABLE
SQL> select file#,block#,status,objd,dirty from v$bh where bjd=13780 and block#=12;
FILE# BLOCK# STATUS OBJD D
---------- ---------- ------- ---------- -
17 12 xcur 13780 N
此时该block为非dirty状态,执行update:
SQL> update cbo.t_16k set id=1 where id=0;
1 row updated.
SQL> commit;
Commit complete.
SQL> select file#,block#,status,objd,dirty from v$bh where bjd=13780 and block#=12;
FILE# BLOCK# STATUS OBJD D
---------- ---------- ------- ---------- -
17 12 cr 13780 N
17 12 xcur 13780 Y
再查看该block的状态,已经多出了一个,应该是用来undo的,另一个的dirty已经变为Y了,说明该数据块已经变为dirty,此时执行查询操作:
SQL> select /*+ parallel(t_16k,5) */ count(*) from cbo.t_16k;
COUNT(*)
----------
10000
SQL> select file#,block#,status,objd,dirty from v$bh where bjd=13780 and block#=12;
FILE# BLOCK# STATUS OBJD D
---------- ---------- ------- ---------- -
17 12 cr 13780 N
17 12 xcur 13780 N
再查看该数据块的状态,已经变为非dirty了,说明该数据块已经被写到磁盘了,可以推断并行查询导致了检查点的发生。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10972173/viewspace-594790/ ,如需转载,请注明出处,否则将追究法律责任。