關於SCN的理解(全面)

tolywang發表於2010-04-02

1.oracle正常執行時,control檔案的SCN是個很大的數,與redo log檔案、資料檔案的SCN不同,正常關閉時,做完checkpoint後,三者的SCN值相同;
Biti:日誌檔案中scn有起始和結束2個(高低),在current log中高scn同樣為無窮大。
2.當一個事務commit成功時,redo log檔案中的SCN+1,當該事務所做的修改寫入資料檔案後,資料檔案的SCN+1;
Biti:commit的時候加1,其他很多時候也會加1,只要資料庫發生了變化都會增加。資料寫入資料檔案時scn不是加1而是由ckpt更新,檢查點發生的時候才修改資料檔案頭的檢查點計數並更新scn。
3.疑問:
是不是如果一個事務比較大,在事務提交前就發生redo log entries、data buffer的寫入,此時斷電,則資料檔案、redo log檔案的SCN沒有+1,且相同,但控制檔案SCN不同,資料庫startup時發生回滾。
Biti:資料檔案是由ckpt程式更新檔案頭的,scn不是加1,而是更新為檢查點發生那時的scn,回滾是根據回滾段頭的事務表狀態來進行的。

4.資料寫入資料檔案scn不是加1而是ckpt 更新,檢查點發生的時候才修改資料檔案頭的 檢查點計數和更新scn
是不是應該這麼說?:
當ckpt 更新時發生資料寫入,同時修改資料檔案頭的 檢查點計數和更新scn 。當出現其他情況下的資料寫入時(如無空閒緩衝等),不發生ckpt ,但SCN會增加。
Biti:這個時候修改的是資料塊但不是資料檔案頭,只有檢查點發生的時候才更新資料檔案頭,也就是說只有ckpt程式更新資料檔案頭(oracle8以前如果沒有ckpt程式就是lgwr更新),dbwr只寫資料塊。

BTW:看樣DBWR只是些資料塊,只有CKPT程式才能更新資料檔案頭;
5.commit的時候加一,其他很多時候也會加1,只要資料庫發生了變化都會增加。
很多時候,能否舉一些例子
Biti:dml一發生即使沒有提交也會增加scn, job程式一樣產生scn,只要對資料庫中檔案發生任何的改變都有可能產生scn,SCN: system change number, not system commit number .也就是系統發生變化時所產生的一個時間點

標誌。不是提交的標誌,只是因為提交也是系統的變化之一而已。

6.Biti:檢查點的發生,跟寫日誌檔案是沒有必然聯絡的
檢查點通知 DBWR 寫資料檔案,寫完後ckpt更新控制檔案頭和資料檔案頭。
當DBWR寫資料塊的時候若發現資料塊的相關 RDBA (位於日誌檔案的位置) 的 log block 還沒有被寫入日誌檔案,則在dbwr寫塊之前必須通知lgwr把log buffer 中日誌寫入日誌檔案。

7.data block 裡面的SCN是當 block 被更改的時候的SCN
而資料檔案有那麼多 block,自然不同的 block有不同的SCN
block中存在 block SCN 和 ITL 中的commit SCN

block SCN 又在塊頭和塊尾都有,若不一致意味著block損壞(熱備可能出現這個情況,需要從redo log中複製回來,若是正在修改的過程中由於程式死掉則 pmon負責清理。若 由於一些以外發生這樣的不一致的情況,則查詢的時候出現 1578 錯誤,當然該錯誤號也可能是物理磁碟損壞,這裡表示邏輯的損壞!)這個頭和尾的SCN的檢查時機跟這兩個引數有關:
db_block_checking boolean FALSE
db_block_checksum boolean FALSE

該2引數資訊請查閱


而ITL 中的 commit SCN 則跟 consistent gets and delay block cleanout 有關

資料檔案頭的 SCN 是檢查點發生時更新的
代表著 當 恢復的時候從這個 SCN 點 開始在 log file 中尋找 redo 開始做恢復

8.According to Rama Velpuri's book, CKPT updates controlfiles, not their headers. It makes sense because if you look at a controlfile dump, the header doesn't even have an SCN. But the file body has sections for each datafile, and therefore each of them has an SCN to be updated.

It's odd that most books and also documentation don't even say CKPT updates controlfiles.

Follow-up to bellsz's original message. In controlfiles, the stop SCN is not a very big number; it's in fact set to infinity when the database is open. Also, SCNs are incremented for many reasons, mostly due to recursive transactions. Read Steve Adams and Hemant Chitale's answers at

9.

系統檢查點scn(v$database(checkpoint_change#))
資料檔案檢查點(v$datafile(checkpoint_change#))
資料檔案終止scn(v$datafile(last_change#))

資料檔案中存放的檢查點
啟動scn (v$datafile_header(checkpoint_change#)

1>系統檢查點scn
當一個檢查點動作完成之後,Oracle就把系統檢查點的SCN儲存到控制檔案中。
select checkpoint_change# from v$database
2>資料檔案檢查點scn
當一個檢查點動作完成之後,Oracle就把每個資料檔案的scn單獨存放在控制檔案
中。
select name,checkpoint_change# from v$datafile
3>啟動scn
Oracle把這個檢查點的scn儲存在每個資料檔案的檔案頭中,這個值稱為啟動scn,
因為它用於在資料庫例項啟動時,檢查是否需要執行資料庫恢復。
select name,checkpoint_change# from v$datafile_header
4>終止scn
每個資料檔案的終止scn都儲存在控制檔案中。
select name,last_change# from v$datafile
在正常的資料庫操作過程中,所有正處於聯機讀寫模式下的資料檔案的終止scn都為null.
5>在資料庫執行期間的scn值
在資料庫開啟並執行之後,控制檔案中的系統檢查點、控制檔案中的資料檔案檢查點scn
和每個資料檔案頭中的啟動scn都是相同的。控制檔案中的每個資料檔案的終止scn都為null.

在安全關閉資料庫的過程中,系統會執行一個檢查點動作,這時所有資料檔案的終止scn
都會設定成資料檔案頭中的那個啟動scn的值。在資料庫重新啟動的時候,
Oracle將檔案頭中的那個啟動scn與資料庫檔案檢查點scn進行比較,
如果這兩個值相互匹配,oracle接下來還要比較資料檔案頭中的啟動scn和控制檔案
中資料檔案的終止scn。如果這兩個值也一致,就意味著所有資料塊多已經提交,所有
對資料庫的修改都沒有在關閉資料庫的過程中丟失,因此這次啟動資料庫的過程
也不需要任何恢復操作,此時資料庫就可以開啟了。當所有的資料庫都開啟之後,
儲存在控制檔案中的資料檔案終止scn的值再次被更改為null,
這表示資料檔案已經開啟並能夠正常使用了。

10.

找了一些網頁,發現SCN確實不只在事務提交時增加,以下是網頁上的摘要:
1)
SCN means "System Change Number" not "System Commit Number".
However, because the SCN is always incremented at commits and seldom otherwise, it is OK to use the two terms interchangeably.
2)
The SCN is incremented whenever a transaction commits. However, this is not the only source of increments. In a seemingly idle database, the SCN gets incremented also through AQ, SMON, job queues...

1中說了oracle seldom操作也會引起SCN的增加,2中更明確說了AQ, SMON, job queues... 會導致SCN的增加,因此應該得出結論,在ORACLE中除了COMMIT會導致SCN增加外還有其它的ORACLE後臺程式會導致SCN增加.

但是,是否是普通的DML導致了SCN的增加,還是由於DML操作過程中後臺程式導致了SCN增加的假象?請大家踴躍討論!
還有ORACLE後臺程式在何時,何種情況下導致了SCN增加,也請大家踴躍討論!

Biti:這句話我應該更準確第表達一下
如果一個dml導致產生事務,則會產生一個scn。這個意思是說
如果一個事務包含多個dml,則只有第一個初始產生事務的dml產生scn,提交的時候又是一個scn
如果一個事務只有一個dml,拿看起來就是dml產生一個scn,提交或者回滾產生一個scn
這是經過實驗測試過的,如果你又興趣,不緊緊是要找資料看,還可以動手證明。

 

你可以理解為 begin transaction and commit tansaction

至於沒有dml的commit ,那不叫一個 transaction

你不做任何dml 而發出rollback命令 將會發現 v$sysstat 中 user rollbacks 將會增加 而 transactions 不會增加

所以你可以把結論定義為 事務的開始 和事務的結束都會導致 SCN 的增加,其他如 AQ/JOB 等也會產生SCN ……
同一個block上在一個事務中連續發生255個DML後scn也會增加
……

11.sys@DBAP01select max(ktuxescnw*power(2,32)+ktuxescnbfrom x$ktuxe;

MAX(KTUXESCNW*POWER(2,32)+
KTUX
------------------------------
                      
52211024
已用時間
:  0000
00.00

sys
@DBAP01alter system checkpoint
;
系統已更改。
已用時間
:  0000
00.06

sys
@DBAP01select CHECKPOINT_CHANGE
# from v$database;
CHECKPOINT_CHANGE
#
------------------
          
52211055
已用時間
:  0000
00.00

sys
@DBAP01select max(ktuxescnw*power(2,32)+ktuxescnbfrom x$ktuxe
;
MAX(KTUXESCNW*POWER(2,32)+
KTUX
------------------------------
                      
52211053
x$ktuxe 計算出來的是已經結束的最新的事務的commit scn ,所以可小於當前系統scn。 檢查點scn 自然也小於當前系統scn。 但是 檢查點scn 和 x$ktuxe 計算出來的大小卻倚賴於 系統狀況了。

current scn 是 系統當前所產生的最大 scn ,可能是當前未結束事務所產生的scn。 在9i 的dbms_flashback.get_system_change_number可以得到這個值,這個值應該是大於等於 x$ktuxe SCN (這個view 記錄的是 當前資料庫結束事務的最大scn) 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/35489/viewspace-659773/,如需轉載,請註明出處,否則將追究法律責任。

相關文章