select current_scn from v$database
union all
select current_scn from v$database;
的结果会是两个相同的SCN,与书中描述的11.2.0.1.0版本中会返回两个不同的SCN的情况不符。
的确,该命令与11.2.0.1.0中的不同,11.2.0.3.0只扫描了X$KCCDI(V$DATABASE的一个基表,提供CURRENT_SCN字段)一次,结果只申请了一个新SCN。
----------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | MERGE JOIN CARTESIAN| |
|* 2 | FIXED TABLE FULL | X$KCCDI |
| 3 | BUFFER SORT | |
| 4 | VIEW | VW_JF_SET$6E0AEE5B |
| 5 | UNION-ALL | |
| 6 | FIXED TABLE FULL| X$KCCDI2 |
| 7 | FIXED TABLE FULL| X$KCCDI2 |
----------------------------------------------------
所以如果想在11.2.0.3.0中也要见到一个SQL访问v$database得到不同current_scn的景象的方案就是:让执行计划扫描X$KCCDI的字段dicur_scn(current_scn)至少两次以上。
a. 办法一:多用几个union all,和优化器比耐心,直到优化器把至少一个X$KCCDI2(V$DATABASE的另一个基表)从VIEW里吐出来,迫使X$KCCDI和X$KCCDI2关联多次,即扫描X$KCCDI多次,比如:
SYS@fmw//Scripts> run
1 select current_scn from v$database
2 union all select current_scn from v$database
3 union all select current_scn from v$database
4* union all select current_scn from v$database
CURRENT_SCN
-----------
5074384
5074385
5074385
5074385
4 rows selected.
这样,X$KCCDI真正被分别扫了两次,所以一共有两个相异的SCN了。其实两个SCN都是当时扫描时的“新”SCN。
b. 办法二:引入另一个对象,比如:
SYS@fmw//Scripts> run
1 select current_scn,status from v$database,v$instance
2 union all
3* select current_scn,status from v$database,v$instance
CURRENT_SCN + STATUS
----------- + ------------------------
5075463 + OPEN
5075464 + OPEN
2 rows selected.
c. 办法三:或者用下面这个查询:
SYS@fmw//Scripts> run
1* select a.current_scn,b.current_scn from v$database a,v$database b
CURRENT_SCN + CURRENT_SCN
----------- + -----------
5078328 + 5078329
1 row selected.
当然这连UNION ALL都没有用到。
d. 最后,当然在X$KCCDI上直接多次查询就行了。这其实有违我的“亲民”路线=D,我一般不太希望拿X$什么什么和什么什么$的说事,有故作神秘之嫌,不过由于V$DATABASE和优化器不给面子这次只能俗气一把了:
SYS@fmw//Scripts> run
1 select dicur_scn from x$kccdi
2* union all select dicur_scn from x$kccdi
DICUR_SCN
--------------------------------
5082183
5082184
2 rows selected.
SYS@fmw//Scripts> run
1* select a.dicur_scn,b.dicur_scn from x$kccdi a,x$kccdi b
DICUR_SCN + DICUR_SCN
-------------------------------- + --------------------------------
5082913 + 5082914
1 row selected.
包光磊
Todd Bao
所以,就像我的书里提到的那样,想要获得真正的当前SCN,不要去问V$DATABASE.CURRENT_SCN要,它给的实际上是“next scn”。
×注意,这次的demo采用的是11.2.0.3.版本。