为了弄清楚consistent read 和 current read的概念,上网搜了一下,并做了一些实验。下面是我的理解和实验过程。 如有不对的地方,望指正出来,谢谢:)
consistent read :
我的理解,就是通过scn来读取。 读取的过程中要保证 scn是一致的。举个例子,一个SELECT 语句在SCN=100的时刻开始读取一系列数据块。在执行的过程中,他发现一个数据块的SCN变成了101,也就是说这个数据块被更改过了。那么 SELECT 就不去读取这个数据块了,而是去读取它的一个早期版本 ,scn=100的这个版本。 这个版本应该在undo空间中。 这就是CONSISTENT read。 这也许让你想到了 oracle的 写不影响读 这个机制。 比如一个让update 了一条记录, 只要他没commit, 另一个让在读取这条记录的时候就总是读取原来的值。 但实际上,即使那条更改被commit了, 只要你的select 时间点,或者说scn 早于commit,你看到的仍然是之前commit之前的,也就是你提交select那个时间点的记录。 接下来的第一条例子,就可以证明这一点。
做一个实验,证明上面的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
-
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
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
-
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
3.打开第二个session,输入下面的语句
-
SQL> update t1 set v1='M' where id=2;
-
-
1 row updated.
-
-
Elapsed: 00:00:00.01
- SQL> commit;
整个的执行过程可以这样描述,
session 1 开始了一个update 操作,他通过consistent read(id= 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没有更新。
转自http://www.itpub.net/thread-1737208-1-1.html