天天看點

Oracle ORA_ROWSCN 僞列 說明

一. 官網對該僞列的說明

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