??? 了解一下10g之后可以新加入的偽劣ORA_ROWSCN,在判斷表的更新時間,是否有記錄被修改的時候比較有用。而且在9i之后,SCN號已經可以和時間互相轉換了,所以使用起來是比較方便的。但是要注意的有幾個事情:
?
??? 1、默認情況下ORA_ROWSCN以block為單位記錄SCN,如需精確到單一行,則需在建表時加入rowdependencies選項。
??? 2、將SCN轉換成timestamp時,太久遠的SCN是無法轉換的,測試了一下我機子上大概能轉一周以內的SCN。
??? 3、所有SCN點均為commit的時間,而非dml時間
?
??? 具體例子就不寫了,轉一篇文看一下就全明白了。
?
?
?
-----------------------------
關于ORA_ROWSCN
?
Oracle10g引入了一個新的ORA_ROWSCN的偽列,可以查詢表中記錄最后變更的SCN。這個新的偽列在某些環境下會非常有用,比如執行樂觀鎖定,或者增量數據抽取的時候。但是,默認情況下,每行記錄的ORA_ROWSCN是基于Block的,除非在建表的時候執行開啟行級跟蹤(create table … rowdependencies)。
?
先來簡單理解一下ORA_ROWSCN的實現原理。我們知道,每個Block在頭部是記錄了該block最近事務的SCN的,所以默認情況下,只需要從block頭部直接獲取這個值就可以了,不需要其他任何的開銷,Oracle就能做到這一點。但是這明顯是不精確的,一個block中會有很多行記錄,每次事務不可能影響到整個block中所有的行,所以這是一個非常不精準的估算值,同一個block的所有記錄的ORA_ROWSCN都會是相同的,基本上沒有多大的使用價值。
?
如果在建表的時候開啟行級跟蹤選項,Oracle則可以為每一行記錄精確的SCN,那么顯然不能再直接從block頭部獲取。要獲得足夠的信息,肯定要付出一定的代價,Oracle必須為每一行實際的存儲這個SCN。所以這個行級跟蹤的選項,只能在建表的時候指定,而不能通過alter table來修改現有的表,否則需要修改每一行記錄的物理存儲格式,代價是可想而知的。
?
簡單的做個實驗就可以知道開啟行級跟蹤以后塊記錄格式的不同。建兩個表,一個norowdependencies(默認),一個rowdependencies,然后分別dump出相應的數據塊:
create table t1(i int);
insert into t1 values(1);
insert into t1 values(2);
commit;
create table t2 rowdependencies as select * from t1;
norowdependencies:
?
block_row_dump:
tab 0, row 0, @0×1f9a
tl: 6 fb: –H-FL– lb: 0×1 cc: 1
col 0: [ 2] c1 02
tab 0, row 1, @0×1f94
tl: 6 fb: –H-FL– lb: 0×1 cc: 1
col 0: [ 2] c1 03
end_of_block_dump
?
rowdependencies:
?
block_row_dump:
tab 0, row 0, @0×1f7c
tl: 12 fb: –H-FL– lb: 0×0 cc: 1
dscn 0×0000.00029ae4
col 0: [ 2] c1 02
tab 0, row 1, @0×1f6d
tl: 12 fb: –H-FL– lb: 0×0 cc: 1
dscn 0×0000.00029ae4
col 0: [ 2] c1 03
end_of_block_dump
?
得到行的SCN后,通過SCN_TO_TIMESTAMP函數可以轉化為時間:
?
SQL>? select SCN_TO_TIMESTAMP(ora_rowscn) from t2 where rownum<2;
?
SCN_TO_TIMESTAMP(ORA_ROWSCN)
---------------------------------------------------------------------------
06-JAN-09 05.31.20.000000000 PM
?
樂觀鎖和ORA_ROWSCN
需要select … for update做悲觀鎖定的時候,通過使用ORA_ROWSCN可以改成樂觀鎖定。一開始select數據的時候將ORA_ROWSCN查出來,修改后如果要寫回數據庫之前再比對下最新的ORA_ROWSCN就可以知道這期間數據是否有發生變化。這個Tom在他的大著《Expert Oracle Database Architecture 9i and 10g Programming Techniques and Solutions 》中也是有提到的。
?
增量數據抽取和ORA_ROWSCN
每次抽取后記錄最大的ORA_ROWSCN,下次抽取再基于上一次的SCN來獲得最近修改過的數據即可。在10g之前,很多系統要實現增量數據抽取,要么通過解析日志,要么加觸發器,要么就在表上加一個時間截字段。ORA_ROWSCN其實就是第三種方式,只是這個字段由Oracle來維護,這樣可以避免一些應用繞過時間截去更新其他字段帶來的問題。不過,如果系統中使用了邏輯備庫或者streams等邏輯復制的方案,而數據抽取又是基于邏輯備庫的話,ORA_ROWSCN就可能對抽取后的數據分析有影響了,因為通過這個得到的時間是邏輯備庫上記錄變更的時間,而不是源庫的時間了。當然,如果純粹只是做數據抽取,而不需要使用這個時間來做分析,還是問題不大的,但還是要考慮一旦邏輯備庫出現故障需要重做的,則這個增量抽取要怎么來處理的問題。
?
Metalink上搜一下ORA_ROWSCN可以看到不少相關的bug,所以在生產系統中使用的時候要小心。例如,我在Linux64平臺上的一臺測試庫中,執行以下語句就會碰到ORA-07445的錯誤:
?
SQL> select ora_rowscn from x$bh where rownum<2;
select ora_rowscn from x$bh where rownum<2
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
?
ORA-07445: exception encountered: core dump [qkafix()+212]
[SIGSEGV] [Address not mapped to object] [0x000000004] [] []
--EOF--
?
?
?
?
?
?
-The End-