Oracle逻辑读简介与分析

 

Logical read逻辑读,就是从内存中读取数据块,包含Current readConsistent read

Current read属于Oracle版本读取方式的一种机制,就是说当进行DML操作时,我们需要获取数据块的最新状态,只对最新状态的块进行操作,操作期间锁定数据行。

Consistent read当进行select查询时,发现这个数据块的版本比我们要查找的要新,那么我们只能从UNDO中去查找这个数据的前映像(PRE IMAGE),在回滚段中找到这个数据的前映像后,把前映像和CURRENT的数据块合并,就形成一个CR BLOCK,这样,通过查询CR BLOCK就可以得到一致性的数据了,这就是Consistent read

公式:logical read=db block gets(current read) + consistent gets(consistent read)

Physical read所谓物理读,就是从磁盘中读取数据块。

 

下面的实验来说明上面的Consistent read

1. 现在有表,内容如下:

SQL> select id ,v1,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) from t1;

 ID    V1                       DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

---------- ------------------------                       ------------------------------------

  1     a                                                       68194

  2     b                                                       68195

 

2. session 1 中运行下列语句:

11:34:51 SQL> select v1 from t1 where id=2 and v1='b' and (select count(*) from dba_objects , dba_tables )>1;

V1

------------------------

b

Elapsed: 00:00:31.11

注意,这个语句运行了约半分钟,所以我们有充足的时间在这条语句运行完毕之前,执行第三步。

 

3. 第三步执行了一个update,把id=2,v1='b' 这条记录修改了,并且做了commit

SQL> update t1 set v1='M' where id=2 ;

1 row updated.

Elapsed: 00:00:00.01

SQL> commit;

Commit complete.

Elapsed: 00:00:00.02

复制代码

第三步执行完,第二步才返回结果。我们可以看到,虽然第三步commit了,但是第二步没有返回最新的结果。第二步返回的是其开始时刻 scn的结果。所以,这就是consistent read了。它只根据scn去读取数据块,保证了数据的完整性,即不会被后来的更新所改变。

current read,读取当前的 data block,最新的 data block,比如在update delete的时候就总是current read 因为你要对最新的data block做更改,对过去更改没有任何实际意义。

 

下面是我自己的实验过程:

1. 首先看一下,我的表 id=2这一行的记录。可以看到 id=2对应着 v1=b

SQL> select id ,v1,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) from t1;

        ID V1                       DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

---------- ------------------------ ------------------------------------

         1 a                                                       68194

         2 b                                                       68195

复制代码

 

2. 我们新开一个session,并输入下面的语句:

11:49:06 SQL> update t1 set v1='B' where id=2 and v1='b' and (select count(*) from dba_objects , dba_tables )>1;

0 rows updated.

Elapsed: 00:01:41.14

复制代码

这个SQL执行了一分钟的时间,因为后面的(select count(*) from dba_objects,dba_tables)这个条件非常的耗时。在输入了这条语句,并且该语句运行完之前,我们来做第三步。

 

3.打开第二个session,输入下面的语句:

SQL> update t1 set v1='M' where id=2;

1 row updated.

Elapsed: 00:00:00.01

SQL> commit;

复制代码

因为,第二步要执行一分钟,所以我们有充足的时间在第二步完成之前完成第三步。 可以看到,第三步完成后,第二步才返回结果--更新了0行。

 

整个的执行过程可以这样描述:

session 1开始了一个update操作,他通过consistent readid= 2 , v1='b' 获取了数据块的id

session 2 修改了id=2这一行的数据,变成了id=2,v1='M'

session 1通过一个通过最开始拿到的block id去以current read读取数据块,结果发现数据块不符合filter的条件了id=2 and v1='b'。所以 session 1没有更新。

    由于CR BLOCKCURRENT BLOCKRDBA都是相同的,因此它们会被放到相同的HASH链上。因此如果某些BLOCKCR BLOCK的版本过多,也会导致BUFFER CACHE CHAINS闩锁竞争加剧。

    如果在生成CR BLOCK的过程中,发现UNDO中的PRE IMAGE由于提交的时间比较长,已经被覆盖,那么,就会出现著名的ORA-1555

    如果单位时间内CR BLOCKS CREATED较大,那么应该检查系统的CPU资源是否出现瓶颈,另外要注意检查BUFFER CACHE相关的闩锁,是否存在竞争。

 

buffer Cache chian产生原因:

    当一个会话需要去访问一个内存块时,它首先要去一个像链表一样的结构中去搜索这个数据块是否在内存中,当会话访问这个链表的时候需要获得一个Latch,如果获取失败,将会产生Latch cache buffer chain等待,导致这个等待的原因是访问相同的数据块的会话太多或者这个列表太长(如果读到内存中的数据太多,需要管理数据块的hash列表就会很长,这样会话扫描列表的时间就会增加,持有chache buffer chain latch的时间就会变长,其他会话获得这个Latch的机会就会降低,等待就会增加)。

 

关于我们 | 新闻中心 | 合作伙伴 | 联系我们 |
西安优盛信息技术有限公司  版权所有©2007-2018  陕ICP备07501629号
在线客服系统