一. 官網對該僞列的說明
From:11gR2
Foreach row, ORA_ROWSCN returns the conservative upper bound system change number(SCN) of the most recent change to the row in the current session. Thispseudocolumn is useful for determining approximately when a row was lastupdated.
Itis not absolutely precise, because Oracle tracks SCNs by transaction committedfor the block in which the row resides. You can obtain a more fine-grainedapproximation of the SCN by creating your tables with row-level dependencytracking. Refer to CREATE TABLE ...
NOROWDEPENDENCIES| ROWDEPENDENCIES
for more information on row-level dependency tracking.
ROWDEPENDENCIESSpecify ROWDEPENDENCIES if you want to enable row-level dependency tracking.This setting is useful primarily to allow for parallel propagation inreplication environments. It increases the size of each row by 6 bytes.
NOROWDEPENDENCIESSpecify NOROWDEPENDENCIES if you do not want table to use the row-leveldependency tracking feature. This is the default.
也就是說,使用表的預設建立參數,即norowdependencies時,此時的ora_rawscn 取自data block header的SCN,那麼這時候,對于同一個block裡的row而言,他們的ora_rowscn 是一樣的。
而在建立table時指定為rowdependencies時,那麼會為每行row 儲存一個ora_rowscn. 這樣對于同一個block裡的row,會有多個ora_rowscn 值。通過dump block,可以發現每個row 會多出一個dscn的資訊,該資訊就是用來儲存ora_rowscn的。
如:
tab 0, row 1, @0×1f88
tl: 12 fb: –H-FL– lb: 0×2 cc: 1
dscn 0×0000.00000000
tl: 12 fb: –H-FL– lb: 0×0 cc: 1
dscn 0×0005.105a6cc1
這是同一個row的dump 資訊,第一次dscn 為0. 此時資訊是從itl的Scn/Fsc中獲得的,當itl發生cleanout時會把Scn/Fsc刷到dscn,就是上面的第二段資訊。具體這塊後面會實驗證明。
關于block dump 和 itl 說明,參考:
You cannot use this pseudocolumn in a query to a view.However, you can use it to refer to the underlying table when creating a view.You can also use this pseudocolumn in the WHERE clause of an UPDATE or DELETEstatement.
--不能在視圖使用ora_rowscn僞列
ORA_ROWSCN is not supported for Flashback Query.Instead, use the version query pseudocolumns, which are provided explicitly forFlashback Query. Refer to the SELECT ...
flashback_query_clause
for information on Flashback Query and "VersionQuery Pseudocolumns"
for additional information on thosepseudocolumns.
--ora_rowscn 不支援Flashbackquery。
Restriction on ORA_ROWSCN: This pseudocolumn is notsupported for external tables.
--ora_rowscn 不支援外部表
Example:
Thefirst statement below uses the ORA_ROWSCN pseudocolumn to get the system changenumber of the last operation on the employees table.
SELECT ORA_ROWSCN, last_name
FROM employees
WHERE employee_id = 188;
--使用ORA_ROWSCN擷取該row 最後一次更新時的SCN
The second statement uses the pseudocolumnwith the SCN_TO_TIMESTAMP function to determine the timestamp of the operation:
SELECTSCN_TO_TIMESTAMP(ORA_ROWSCN), last_name
--使用SCN_TO_TIMESTAMP 和 ORA_ROWSCN,擷取最後一次修改row的時間
二. ORA_ROWSCN 說明
ORA_ROWSCN僞列是Oracle10g引入的,可以查詢表中記錄最後變更的SCN。這個新的僞列在某些環境下會非常有用,比如執行樂觀鎖定,或者增量資料抽取的時候。但是,預設情況下,每行記錄的ORA_ROWSCN是基于Block的,除非在建表的時候執行開啟行級跟蹤(createtable … rowdependencies)。
2.1 樂觀鎖和ORA_ROWSCN
需要select ... for update做悲觀鎖定的時候,通過使用ORA_ROWSCN可以改成樂觀鎖定。一開始select資料的時候将ORA_ROWSCN查出來,修改後如果要寫回資料庫之前再比對下最新的ORA_ROWSCN就可以知道這期間資料是否有發生變化。
2.2 增量資料抽取和ORA_ROWSCN
每次抽取後記錄最大的ORA_ROWSCN,下次抽取再基于上一次的SCN來獲得最近修改過的資料即可。在10g之前,很多系統要實作增量資料抽取,要麼通過解析日志,要麼加觸發器,要麼就在表上加一個時間截字段。
ORA_ROWSCN其實就是第三種方式,隻是這個字段由Oracle來維護,這樣可以避免一些應用繞過時間截去更新其他字段帶來的問題。不過,如果系統中使用了邏輯備庫或者streams等邏輯複制的方案,而資料抽取又是基于邏輯備庫的話,ORA_ROWSCN就可能對抽取後的資料分析有影響了,因為通過這個得到的時間是邏輯備庫上記錄變更的時間,而不是源庫的時間了。
當然,如果純粹隻是做資料抽取,而不需要使用這個時間來做分析,還是問題不大的,但還是要考慮一旦邏輯備庫出現故障需要重做的,則這個增量抽取要怎麼來處理的問題。
三. 測試
3.1 基本測試
SYS@anqing2(rac2)> create table rowscn1(idnumber,name varchar2(20));
Table created.
SYS@anqing2(rac2)> insert into rowscn1values(1,'dave');
1 row created.
SYS@anqing2(rac2)> commit;
Commit complete.
SYS@anqing2(rac2)> SELECT
2 dbms_rowid.rowid_relative_fno(rowid) REL_FNO,
3 dbms_rowid.rowid_block_number(rowid) BLOCKNO,
dbms_rowid.rowid_row_number(rowid) ROWNO,
id,name from rowscn1; 4 5
REL_FNO BLOCKNO ROWNO ID NAME
---------- ---------- ---------- ------------------------------
1 305890 0 1 dave
1 305890 1 1 dave
SYS@anqing2(rac2)> select ora_rowscn,idfrom rowscn1;
ORA_ROWSCN ID
---------- ----------
7233799 1
在預設情況下,使用的是block header的SCN,是以這時候,如果我們就該該表的資訊,block header 的scn 發生改變,那麼對應block上所有的ora_rowscn 也會發生改變。
SYS@anqing2(rac2)> insert into rowscn1values(2,'anqing');
SYS@anqing2(rac2)> select ora_rowscn,id from rowscn1;
7233940 1
7233940 2
這個和我們上面的理論一緻。
3.2 rowdependencies/norowdependencies 與ora_rowscn測試
SYS@anqing2(rac2)> create tablerowscn2(id number,name varchar2(20)) rowdependencies;
啟動行級别的跟蹤。
SYS@anqing2(rac2)> insert into rowscn2values(1,'dave');
SYS@anqing2(rac2)> insert into rowscn2values(2,'anqing');
id,name from rowscn2;
4 5
1 305898 0 1 dave
1 305898 1 2 anqing
SYS@anqing2(rac2)> select ora_rowscn,idfrom rowscn2;
7234177 1
7234177 2
測試2個ora_rowscn 是一樣的。 我們把這個block dump 出來看一下:
SYS@anqing2(rac2)> oradebug setmypid
Statement processed.
SYS@anqing2(rac2)> alter system dump datafile 1 block 305898;
System altered.
SYS@anqing2(rac2)> oradebugtracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_22260.trc
[oracle@rac2 ~]$ cat/u01/app/oracle/admin/anqing/udump/anqing2_ora_22260.trc
Oracle Database 10g Enterprise EditionRelease 10.2.0.4.0 - Production
With the Partitioning, Real ApplicationClusters, OLAP, Data Mining
and Real Application Testing options
ORACLE_HOME =/u01/app/oracle/product/10.2.0/db_1
System name: Linux
Node name: rac2
Release: 2.6.18-194.el5
Version: #1 SMP Tue Mar 16 21:52:43 EDT 2010
Machine: i686
Instance name: anqing2
Redo thread mounted by this instance: 2
Oracle process number: 20
Unix process pid: 22260, image: oracle@rac2(TNS V1-V3)
*** 2011-08-04 00:35:21.673
*** ACTION NAME:() 2011-08-04 00:35:21.673
*** MODULE NAME:(sqlplus@rac2 (TNS V1-V3))2011-08-04 00:35:21.673
*** SERVICE NAME:(SYS$USERS) 2011-08-0400:35:21.673
*** SESSION ID:(148.61626) 2011-08-0400:35:21.673
Start dump data blocks tsn: 0 file#: 1minblk 305898 maxblk 305898
buffer tsn: 0 rdba: 0x0044aaea (1/305898)
scn: 0x0000.006e6281 seq: 0x01 flg: 0x02tail: 0x62810601
frmt: 0x02 chkval: 0x0000 type: 0x06=transdata
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0EAF6400 to0x0EAF8400
.....
Block header dump: 0x0044aaea
Object id on Block? Y
seg/obj: 0xdbdd csc: 0x00.6e627d itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000e.004.000003cf 0x0140003b.00ce.10 --U- 2 fsc 0x0000.006e6281
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
data_block_dump,data header at 0xeaf645c
===============
tsiz: 0x1fa0
hsiz: 0x16
pbl: 0x0eaf645c
bdba: 0x0044aaea
76543210
flag=--R-----
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f7c
avsp=0x1f66
tosp=0x1f66
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f8f
0x14:pri[1] offs=0x1f7c
block_row_dump:
tab 0, row 0, @0x1f8f
tl: 17 fb: --H-FL-- lb: 0x1 cc: 2
dscn 0x0000.00000000
col 0: [ 2] c1 02
col 1: [ 4] 64 61 76 65
tab 0, row 1, @0x1f7c
tl: 19 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [ 6] 61 6e 71 69 6e 67
end_of_block_dump
End dump data blocks tsn: 0 file#: 1 minblk305898 maxblk 305898
此時測dscn 為0. 在前面講過, ora_rwscn 是在itl 發生cleanout 時刷到dscn的。 我們在進行一些事務操作檢視一下。
SYS@anqing2(rac2)> select * fromrowscn2;
ID NAME
---------- --------------------
1 dave
2 anqing
SYS@anqing2(rac2)> update rowscn2 setid=3 where id=1;
1 row updated.
SYS@anqing2(rac2)> update rowscn2 setid=4 where id=2;
7234500 3
7234509 4
--測試的ora_rowscn已經發生改變
我們dump 看一下:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000c.005.0000042a 0x01400101.016d.34 --U- 1 fsc 0x0000.006e63cd
0x02 0x000e.006.000003cb 0x0140003b.00ce.11 --U- 1 fsc0x0000.006e63c4
tl: 17 fb: --H-FL-- lb: 0x2 cc: 2
dscn 0x0000.006e6281
col 0: [ 2] c1 04
col 0: [ 2] c1 05
注意這裡的dscn 還是一樣的,這就是說,我們剛才通過select 查詢的結果一個是從dscn出來的,還有一個是從itl裡出來的。 我們在進行一些事務操作。
SYS@anqing2(rac2)> insert into rowscn2values(1,'huaining');
SYS@anqing2(rac2)> insert into rowscn2values(2,'dmm');
7234673 1
7234683 2
再次dump block:
0x01 0x000b.02d.000003d4 0x01400042.00c0.16 --U- 1 fsc 0x0000.006e647b
0x02 0x0013.003.000003b4 0x0140008f.00c2.12 --U- 1 fsc 0x0000.006e6471
tl: 17 fb: --H-FL-- lb: 0x0 cc: 2
dscn 0x0000.006e63c4
tl: 19 fb: --H-FL-- lb: 0x0 cc: 2
dscn 0x0000.006e63cd
tab 0, row 2, @0x1f67
tl: 21 fb: --H-FL-- lb: 0x2 cc: 2
col 1: [ 8] 68 75 61 69 6e 69 6e 67
tab 0, row 3, @0x1f57
tl: 16 fb: --H-FL-- lb: 0x1 cc: 2
col 1: [ 3] 64 6d 6d
--測試我們的前兩條記錄的dscn 值不一樣了。
最後執行一下官網有關時間的一個測試:
SYS@anqing2(rac2)> col SCN_TO_TIMESTAMP(ORA_ROWSCN)for a35
SYS@anqing2(rac2)> selectscn_to_timestamp(ora_rowscn),id,name from rowscn2;
SCN_TO_TIMESTAMP(ORA_ROWSCN) ID NAME
--------------------------------------------- --------------------
04-AUG-11 12.39.42.000000000 AM 3 dave
04-AUG-11 12.39.54.000000000 AM 4 anqing
04-AUG-11 12.44.27.000000000 AM 1 huaining
04-AUG-11 12.44.39.000000000 AM 2 dmm