Oracle SCN詳解
Oracle中的SCN(system change number)和我們的北京時間的意義是相同的,SCN是Oracle中的時間號。
為什麼Oracle不用時間來界定呢?
我在北京時間8:00的時候執行一條DML語句,然後修改機器上的時間為7:00,再執行一條DML語句。如果用機器上的時間區分的話,那Oracle根本區分不出來這兩條DML語句的執行順序——而這一點對於Oracle是很重要的。所以它採用自己產生的SCN來區分所有操作的先後順序。
SCN設計的值很大,所以不用擔心達到最大值後怎麼辦。
可以檢視系統當前的SCN號:
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
464640326
也可以檢視系統當前儲存的SCN號:
SQL> select checkpoint_change# from v$database
CHECKPOINT_CHANGE#
------------------
464639929
如果此時資料庫損壞,當重啟時候需要修復的,就是這兩個SCN之間的資料。這些資料儲存在線上重做日誌檔案中:
SQL> select GROUP#, STATUS, FIRST_CHANGE# from v$log;
GROUP# STATUS FIRST_CHANGE#
---------- ------------------------------ -------------
1 INACTIVE 464633029
2 INACTIVE 464637664
3 CURRENT 464638303
group1中儲存的資料產生的SCN號為 464633029 至 464637664;group2中的SCN號為 464637664 至 464638303;group3中的SCN號為 464638303 至 464640326(當前SCN號)。
所以,若此時執行shutdown abort並重啟,執行crash recovery時,使用的線上重做日誌檔案為group3中的member。而透過v$log.status欄位也能看到:group3的狀態為current。
Part I. 透析SCN號
SCN是當Oracle資料庫更新後,由DBMS自動維護去累積遞增的一個數字。當一筆交易commit時,LGWR會將log buffer寫入redo log file,同時也會將該筆交易的SCN同步寫入到redo log file內(wait-until-completed)。因此當你commit transaction時,在交易成功的訊息返回之前,LGWR必須先完整的完成上述行為之後,否則你是看不到提交成功的回應訊息。
可以查詢目前系統最新的SCN
SQL>select dbms_flashback.get_system_change_number from dual;
SQL>select dbms_flashback.get_system_change_number from dual;
可以理解,這裡返回的SCN,也是目前redo log file最新的SCN紀錄。因為commit後的交易才會有SCN,而一旦commit就會立刻寫入redo log file中。
CHECKPOINT和SCN的關聯
Checkpoint發生的目的就是要把儲存在buffer內的已提交交易寫回disk,否則一旦發生crash,需要進行recovery時,就必須花很多時間從redo log file內最後的SCN交易開始進行recovery,這樣在商業應用上是很浪費時間和沒有效率的。
Checkpoint發生的目的就是要把儲存在buffer內的已提交交易寫回disk,否則一旦發生crash,需要進行recovery時,就必須花很多時間從redo log file內最後的SCN交易開始進行recovery,這樣在商業應用上是很浪費時間和沒有效率的。
當commit一筆交易時,只會立刻將redo buffer寫入redo log file內,但是並不會馬上將該update後的block(dirty block)同步寫回disk datafile中,這是為了減少過多disk IO,所以採取batch方式寫入。
When a checkpoint occurs. Oracle must update the headers of all datafiles to record the details of the checkpoint. This is done by the CKPT process. The CKPT process does not write blocks to disk; DBWn always performs that work.
在shutdown normal or shutdown immediate下,也就是所謂的clean shutdown, checkpoint也會自動觸發。當發生checkpoint時,會把SCN寫到四個地方去。三個地方在control file 內,一個在datafile header。
Control file三個地方為:
1、 System checkpoint SCN
SQL> select to_char(checkpoint_change#, 'XXXXXXXXXXXX') from v$database;
1、 System checkpoint SCN
SQL> select to_char(checkpoint_change#, 'XXXXXXXXXXXX') from v$database;
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-----------------------------------------------------------------
7161D7365DC
-----------------------------------------------------------------
7161D7365DC
2、 Datafile checkpoint SCN
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile where name like '%gisdts01%';
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile where name like '%gisdts01%';
NAME
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7365DC
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7365DC
3、 Stop SCN
SQL> select name,last_change# from v$datafile where name like '%gisdts01%';
NAME
--------------------------------
/gisdata/datafile/gisdts01.dbf
正常datafile在read-write mode運作下,last_change#一定是null
SQL> select name,last_change# from v$datafile where name like '%gisdts01%';
NAME
--------------------------------
/gisdata/datafile/gisdts01.dbf
正常datafile在read-write mode運作下,last_change#一定是null
還有一個SCN在datafile header內
4、 Start SCN
SQL>select name,to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile_header where name like '%gisdts01%';
NAME
---------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
---------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7365DC
為什麼儲存在control file中要分為兩個地方(system checkpoint scn, datafile checkpoint scn?)。當把一個tbs設為read-only時,他的scn會凍結停止,此時datafile checkpoint scn是不會再遞增改變的,但是整體的system checkpoint scn卻仍然會不斷遞增前進。所以這是為什麼需要分別在兩個地方儲存SCN。
正常shutdown database後,SCN會發生什麼變化?
可以把資料庫開在mount mode
SQL> select to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$database;
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
7161D7455B9
SQL>select name,to_char(checkpoint_change#,’XXXXXXXXXXXX’),to_char(last_change#
,’XXXXXXXXXXXX’) from v$datafile where name like '%gisdts01%';
NAME
-------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
TO_CHAR(LAST_CHANGE#,'XXXXXXXX
-------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
7161D7455B9
可以看到儲存在control file中的三個SCN的數值都是相同的,注意此時的stop scn不會是null,而是等於start scn。
再來查詢datafile header中的SCN:
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile_hea
der where name like '%gisdts01%';
NAME
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
可以把資料庫開在mount mode
SQL> select to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$database;
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
7161D7455B9
SQL>select name,to_char(checkpoint_change#,’XXXXXXXXXXXX’),to_char(last_change#
,’XXXXXXXXXXXX’) from v$datafile where name like '%gisdts01%';
NAME
-------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------
TO_CHAR(LAST_CHANGE#,'XXXXXXXX
-------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
7161D7455B9
可以看到儲存在control file中的三個SCN的數值都是相同的,注意此時的stop scn不會是null,而是等於start scn。
再來查詢datafile header中的SCN:
SQL> select name, to_char(checkpoint_change#,'XXXXXXXXXXXX') from v$datafile_hea
der where name like '%gisdts01%';
NAME
-------------------------------------------------------------------
TO_CHAR(CHECKPOINT_CHANGE#,'XX
-------------------------------------------------------------------
/gisdata/datafile/gisdts01.dbf
7161D7455B9
當clean shutdown時,checkpoint會進行,並且此時datafile的stop scn和start scn會相同。等我們開啟資料庫時,oracle會檢查datafile header中的start scn和存於control file中的datafile的scn是否相同,如果相同,接著檢查start scn和stop scn是否相同,如果仍然相同,資料庫會正常啟動,否則就需要recovery….等到資料庫open後,儲存在control file中的stop scn就會恢復為null值,此時表示datafile是open在正常模式下。
如果不正常shutdown(shutdown abort),則mount資料庫後,會發現stop scn並不等於其它位置的scn,而是等於null。這表示oracle在shutdown時沒有進行checkpoint,下次啟動必須進行crash recovery。
如果不正常shutdown(shutdown abort),則mount資料庫後,會發現stop scn並不等於其它位置的scn,而是等於null。這表示oracle在shutdown時沒有進行checkpoint,下次啟動必須進行crash recovery。
Part II. Oracle SCN機制解析
SCN(System Chang Number)作為oracle中的一個重要機制,在資料恢復、Data Guard、Streams複製、RAC節點間的同步等各個功能中起著重要作用。理解SCN的運作機制,可以幫助你更加深入地瞭解上述功能。
在理解SCN之前,我們先看下oracle事務中的資料變化是如何寫入資料檔案的:
1、 事務開始;
2、 在buffer cache中找到需要的資料塊,如果沒有找到,則從資料檔案中載入buffer cache中;
3、 事務修改buffer cache的資料塊,該資料被標識為“髒資料”,並被寫入log buffer中;
4、 事務提交,LGWR程式將log buffer中的“髒資料”寫入redo log file中;
5、 當發生checkpoint,CKPT程式更新所有資料檔案的檔案頭中的資訊,DBWn程式則負責將Buffer Cache中的髒資料寫入到資料檔案中。
經過上述5個步驟,事務中的資料變化最終被寫入到資料檔案中。但是,一旦在上述中間環節時,資料庫意外當機了,在重新啟動時如何知道哪些資料已經寫入資料檔案、哪些沒有寫呢(同樣,在DG、streams中也存在類似疑問:redo log中哪些是上一次同步已經複製過的資料、哪些沒有)?SCN機制就能比較完善的解決上述問題。
SCN是一個數字,確切的說是一個只會增加、不會減少的數字。正是它這種只會增加的特性確保了Oracle知道哪些應該被恢復、哪些應該被複制。
總共有4中SCN:系統檢查點(System Checkpoint)SCN、資料檔案檢查點(Datafile Checkpoint)SCN、結束SCN(Stop SCN)、開始SCN(Start SCN)。其中其面3中SCN存在於控制檔案中,最後一種則存在於資料檔案的檔案頭中。
在控制檔案中,System Checkpoint SCN是針對整個資料庫全域性的,因而之存在一個,而Datafile Checkpoint SCN和Stop SCN是針對每個資料檔案的,因而一個資料檔案就對應在控制檔案中存在一份Datafile Checkpoint SCN和Stop SCN。在資料庫正常執行期間,Stop SCN(透過檢視v$datafile的欄位last_change#可以查詢)是一個無窮大的數字或者說是NULL。
在一個事務提交後(上述第四個步驟),會在redo log中存在一條redo記錄,同時,系統為其提供一個最新的SCN(透過函式dbms_flashback.get_system_change_number可以知道當前的最新SCN),記錄在該條記錄中。如果該條記錄是在redo log被清空(日誌滿做切換時或發生checkpoint時,所有變化日誌已經被寫入資料檔案中),則其SCN被記錄為redo log的low SCN。以後在日誌再次被清空前寫入的redo記錄中SCN則成為Next SCN。
當日志切換或發生checkpoint(上述第五個步驟)時,從Low SCN到Next SCN之間的所有redo記錄的資料就被DBWn程式寫入資料檔案中,而CKPT程式則將所有資料檔案(無論redo log中的資料是否影響到該資料檔案)的檔案頭上記錄的Start SCN(透過檢視v$datafile_header的欄位checkpoint_change#可以查詢)更新為Next SCN,同時將控制檔案中的System Checkpoint SCN(透過檢視v$database的欄位checkpoint_change#可以查詢)、每個資料檔案對應的Datafile Checkpoint(透過檢視v$datafile的欄位checkpoint_change#可以查詢)也更新為Next SCN。但是,如果該資料檔案所在的表空間被設定為read-only時,資料檔案的Start SCN和控制檔案中Datafile Checkpoint SCN都不會被更新。
那系統是如何產生一個最新的SCN的?實際上,這個數字是由當時的timestamp轉換過來的。每當需要產生一個最新的SCN到redo記錄時,系統獲取當時的timestamp,將其轉換為數字作為SCN。我們可以透過函式SCN_TO_TIMESTAMP(10g以後)將其轉換回timestamp:
SQL> select dbms_flashback.get_system_change_number, SCN_TO_TIMESTAMP(dbms_flashback
.get_system_change_number) from dual;
.get_system_change_number) from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
SCN_TO_TIMESTAMP(DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER)
---------------------------------------------------------------------------
2877076756
17-AUG-07 02.15.26.000000000 PM
也可以用函式timestamp_to_scn將一個timestamp轉換為SCN:
SQL> select timestamp_to_scn(SYSTIMESTAMP) as scn from dual;
SCN
----------
2877078439
最後,SCN除了作為反映事務資料變化並保持同步外,它還起到系統的“心跳”作用——每隔3秒左右系統會重新整理一次系統SCN。
下面,在簡單介紹一下SCN如何在資料庫恢復中起作用。
資料庫在正常關閉(shutdown immediate/normal)時,會先做一次checkpoint,將log file中的資料寫入資料檔案中,將控制檔案、資料檔案中的SCN(包括控制檔案中的Stop SCN)都更新為最新的SCN。
資料庫異常/意外關閉不會或者只更新部分Stop SCN。
當資料庫啟動時,Oracle先檢查控制檔案中的每個Datafile Checkpoint SCN和資料檔案中的Start SCN是否相同,再檢查每個Datafile Checkpoint SCN和Stop SCN是否相同。如果發現有不同,就從Redo Log中找到丟失的SCN,重新寫入資料檔案中進行恢復。具體的資料恢復過程這裡就不再贅述。
SCN作為Oracle中的一個重要機制,在多個重要功能中起著“控制器”的作用。瞭解SCN的產生和實現方式,幫助DBA理解和處理恢復、DG、Streams複製的問題。
最後提一句,利用SCN機制,在Oracle10g、11g中又增加了一些很實用的功能——資料庫閃回、資料庫負載重現等。
Part III. scn(系統改變號)資訊與恢復
control中有三種SCN分別為,system SCN、datafile SCN、last SCN,資料檔案頭中有一種SCN start SCN
system scn從檢視v$database中獲得,對應checkpoint_change#欄位,datafile scn、last scn分別對應檢視v$datafile中的checkpoint_change#,last_change#,而 start scn則從v$datafile_header中checkpoint_change#得到。
資料庫在正常啟動後下,system scn,datafile scn,start scn會相等,而last scn會被置於無窮大,這裡為null。
正常關閉後(immediate,noraml,translate),上面四個scn會應執行full checkpoint 而相等。
當系統在非正常關閉後,如shutdown abort,這個時候last scn依然為無窮大,那麼當重新啟動例項時,系統首先會比較start scn與system scn,如果一致,那麼再比較start scn 與last scan是否一樣大,因為是非正常關閉,這裡會不一樣大,那麼就需要例程恢復。
如果開啟資料庫時發現system scn>datafile scn,那麼以為著使用舊的備份資料檔案,也就是需要介質恢復
如果是system scn<datafile scn,及控制檔案scn是舊的,代表使用了老的控制檔案,需要recover using backup controlfile進行恢復。
system scn從檢視v$database中獲得,對應checkpoint_change#欄位,datafile scn、last scn分別對應檢視v$datafile中的checkpoint_change#,last_change#,而 start scn則從v$datafile_header中checkpoint_change#得到。
資料庫在正常啟動後下,system scn,datafile scn,start scn會相等,而last scn會被置於無窮大,這裡為null。
正常關閉後(immediate,noraml,translate),上面四個scn會應執行full checkpoint 而相等。
當系統在非正常關閉後,如shutdown abort,這個時候last scn依然為無窮大,那麼當重新啟動例項時,系統首先會比較start scn與system scn,如果一致,那麼再比較start scn 與last scan是否一樣大,因為是非正常關閉,這裡會不一樣大,那麼就需要例程恢復。
如果開啟資料庫時發現system scn>datafile scn,那麼以為著使用舊的備份資料檔案,也就是需要介質恢復
如果是system scn<datafile scn,及控制檔案scn是舊的,代表使用了老的控制檔案,需要recover using backup controlfile進行恢復。
1、正常啟動時
SQL> select checkpoint_change# from v$database; --控制檔案中的scn
SQL> select checkpoint_change# from v$database; --控制檔案中的scn
CHECKPOINT_CHANGE#
------------------
5534071
SQL> select file#,checkpoint_change# from v$datafile_header; --start scn
------------------
5534071
SQL> select file#,checkpoint_change# from v$datafile_header; --start scn
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
SQL> select file#,checkpoint_change#,last_change# from v$datafile; --datafile scn & last scn
---------- ------------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
SQL> select file#,checkpoint_change#,last_change# from v$datafile; --datafile scn & last scn
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
2、正常關閉後,然後在startup mount;
SQL> shutdown immediate;
資料庫已經關閉。
已經解除安裝資料庫。
ORACLE 例程已經關閉。
SQL> startup mount;
ORACLE 例程已經啟動。
---------- ------------------ ------------
1 5534071
2 5534071
3 5534071
4 5534071
5 5534071
2、正常關閉後,然後在startup mount;
SQL> shutdown immediate;
資料庫已經關閉。
已經解除安裝資料庫。
ORACLE 例程已經關閉。
SQL> startup mount;
ORACLE 例程已經啟動。
Total System Global Area 319888364 bytes
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
SQL> select file#,checkpoint_change# from v$datafile_header;
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534485
2 5534485
3 5534485
4 5534485
5 5534485
---------- ------------------
1 5534485
2 5534485
3 5534485
4 5534485
5 5534485
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------
5534485
------------------
5534485
SQL> select file#,checkpoint_change#,last_change# from v$datafile;
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534485 5534485
2 5534485 5534485
3 5534485 5534485
4 5534485 5534485
5 5534485 5534485
--發現start scn=last scn,證明系統是正常關閉
---------- ------------------ ------------
1 5534485 5534485
2 5534485 5534485
3 5534485 5534485
4 5534485 5534485
5 5534485 5534485
--發現start scn=last scn,證明系統是正常關閉
SQL> alter database open;
資料庫已更改。
3、在正常開啟狀態下進行事務操作
SQL> create table t(a number);
SQL> create table t(a number);
表已建立。
SQL> insert into t values (1);
已建立 1 行。
SQL> commit;
提交完成。
SQL> insert into t values(2);
已建立 1 行。
4、非正常關閉
SQL> shutdown abort;
ORACLE 例程已經關閉。
SQL>
SQL> shutdown abort;
ORACLE 例程已經關閉。
SQL>
5、開啟到mount狀態下,觀看scn
SQL> startup mount;
ORACLE 例程已經啟動。
SQL> startup mount;
ORACLE 例程已經啟動。
Total System Global Area 319888364 bytes
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
SQL> select file#,checkpoint_change#,last_change# from v$datafile;
Fixed Size 453612 bytes
Variable Size 192937984 bytes
Database Buffers 125829120 bytes
Redo Buffers 667648 bytes
資料庫裝載完畢。
SQL> select file#,checkpoint_change#,last_change# from v$datafile;
FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
---------- ------------------ ------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------
5534486
------------------
5534486
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
---------- ------------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
--這時發現start scn 與last scn不等,last scn為無窮大,需要例程恢復
---------- ------------------
1 5534486
2 5534486
3 5534486
4 5534486
5 5534486
--這時發現start scn 與last scn不等,last scn為無窮大,需要例程恢復
6、改變資料庫狀態為open,並檢視該階段執行日誌
SQL> select * from wen.t;
select * from wen.t
*
ERROR 位於第 1 行:
ORA-01219: 資料庫未開啟: 僅允許在固定表/檢視中查詢
SQL> select * from wen.t;
select * from wen.t
*
ERROR 位於第 1 行:
ORA-01219: 資料庫未開啟: 僅允許在固定表/檢視中查詢
SQL> alter database open;
資料庫已更改。
SQL> select * from wen.t;
SQL> select * from wen.t;
A
----------
1
--發現沒有提交的事務丟失。
檢視日誌如下:
Completed: ALTER DATABASE MOUNT
Wed May 17 21:35:46 2006
alter database open
Wed May 17 21:35:46 2006
Beginning crash recovery of 1 threads --會自動判斷是否需要恢復,這裡開始例程恢復
Wed May 17 21:35:46 2006
Started first pass scan
Wed May 17 21:35:47 2006
Completed first pass scan
206 redo blocks read, 90 data blocks need recovery
Wed May 17 21:35:47 2006
Started recovery at
Thread 1: logseq 167, block 271, scn 0.0
Recovery of Online Redo Log: Thread 1 Group 2 Seq 167 Reading mem 0 --恢復用的線上重做日誌
Mem# 0 errs 0: D:ORACLEORADATADB1REDO02.LOG
Wed May 17 21:35:47 2006
Ended recovery at
Thread 1: logseq 167, block 477, scn 0.5554724
90 data blocks read, 90 data blocks written, 206 redo blocks read
Crash recovery completed successfully --恢復完成
Wed May 17 21:35:47 2006
LGWR: Primary database is in CLUSTER CONSISTENT mode
Thread 1 advanced to log sequence 168
Thread 1 opened at log sequence 168
Current log# 3 seq# 168 mem# 0: D:ORACLEORADATADB1REDO03.LOG
Successful open of redo thread 1.
Wed May 17 21:35:48 2006
SMON: enabling cache recovery
Wed May 17 21:35:48 2006
ARC0: Evaluating archive log 2 thread 1 sequence 167
ARC0: Beginning to archive log 2 thread 1 sequence 167
Creating archive destination LOG_ARCHIVE_DEST_1: 'D:DBBKARC00167.001'
ARC0: Completed archiving log 2 thread 1 sequence 167
Wed May 17 21:35:48 2006
Undo Segment 1 Onlined
Undo Segment 2 Onlined
Undo Segment 3 Onlined
Undo Segment 4 Onlined
Undo Segment 5 Onlined
Undo Segment 6 Onlined
----------
1
--發現沒有提交的事務丟失。
檢視日誌如下:
Completed: ALTER DATABASE MOUNT
Wed May 17 21:35:46 2006
alter database open
Wed May 17 21:35:46 2006
Beginning crash recovery of 1 threads --會自動判斷是否需要恢復,這裡開始例程恢復
Wed May 17 21:35:46 2006
Started first pass scan
Wed May 17 21:35:47 2006
Completed first pass scan
206 redo blocks read, 90 data blocks need recovery
Wed May 17 21:35:47 2006
Started recovery at
Thread 1: logseq 167, block 271, scn 0.0
Recovery of Online Redo Log: Thread 1 Group 2 Seq 167 Reading mem 0 --恢復用的線上重做日誌
Mem# 0 errs 0: D:ORACLEORADATADB1REDO02.LOG
Wed May 17 21:35:47 2006
Ended recovery at
Thread 1: logseq 167, block 477, scn 0.5554724
90 data blocks read, 90 data blocks written, 206 redo blocks read
Crash recovery completed successfully --恢復完成
Wed May 17 21:35:47 2006
LGWR: Primary database is in CLUSTER CONSISTENT mode
Thread 1 advanced to log sequence 168
Thread 1 opened at log sequence 168
Current log# 3 seq# 168 mem# 0: D:ORACLEORADATADB1REDO03.LOG
Successful open of redo thread 1.
Wed May 17 21:35:48 2006
SMON: enabling cache recovery
Wed May 17 21:35:48 2006
ARC0: Evaluating archive log 2 thread 1 sequence 167
ARC0: Beginning to archive log 2 thread 1 sequence 167
Creating archive destination LOG_ARCHIVE_DEST_1: 'D:DBBKARC00167.001'
ARC0: Completed archiving log 2 thread 1 sequence 167
Wed May 17 21:35:48 2006
Undo Segment 1 Onlined
Undo Segment 2 Onlined
Undo Segment 3 Onlined
Undo Segment 4 Onlined
Undo Segment 5 Onlined
Undo Segment 6 Onlined
Part IV. 關於SCN的理解
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,回滾是根據回滾段頭的事務表狀態來進行的。
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只寫資料塊。
是不是應該這麼說?:
當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 .也就是系統發生變化時所產生的一個時間點
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 中日誌寫入日誌檔案。
檢查點通知 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,自然不同的 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
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 開始做恢復
代表著 當 恢復的時候從這個 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.
9.
系統檢查點scn(v$database(checkpoint_change#))
資料檔案檢查點(v$datafile(checkpoint_change#))
資料檔案終止scn(v$datafile(last_change#))
資料檔案檢查點(v$datafile(checkpoint_change#))
資料檔案終止scn(v$datafile(last_change#))
資料檔案中存放的檢查點
啟動scn (v$datafile_header(checkpoint_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.
當一個檢查點動作完成之後,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,
這表示資料檔案已經開啟並能夠正常使用了。
都會設定成資料檔案頭中的那個啟動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)
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增加,也請大家踴躍討論!
還有ORACLE後臺程式在何時,何種情況下導致了SCN增加,也請大家踴躍討論!
Biti:這句話我應該更準確第表達一下
如果一個dml導致產生事務,則會產生一個scn。這個意思是說
如果一個事務包含多個dml,則只有第一個初始產生事務的dml產生scn,提交的時候又是一個scn
如果一個事務只有一個dml,拿看起來就是dml產生一個scn,提交或者回滾產生一個scn
這是經過實驗測試過的,如果你又興趣,不緊緊是要找資料看,還可以動手證明。
如果一個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也會增加
……
同一個block上在一個事務中連續發生255個DML後scn也會增加
……
> select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe;
MAX(KTUXESCNW*POWER(2,32)+KTUX
------------------------------
52211024
已用時間: 00: 00: 00.00
------------------------------
52211024
已用時間: 00: 00: 00.00
> alter system checkpoint;
系統已更改。
已用時間: 00: 00: 00.06
系統已更改。
已用時間: 00: 00: 00.06
> select CHECKPOINT_CHANGE# from v$database;
CHECKPOINT_CHANGE#
------------------
52211055
已用時間: 00: 00: 00.00
CHECKPOINT_CHANGE#
------------------
52211055
已用時間: 00: 00: 00.00
> select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe;
MAX(KTUXESCNW*POWER(2,32)+KTUX
------------------------------
52211053
x$ktuxe 計算出來的是已經結束的最新的事務的commit scn ,所以可小於當前系統scn。 檢查點scn 自然也小於當前系統scn。 但是 檢查點scn 和 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)
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/daimin1983/archive/2008/12/09/3484173.aspx
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31444259/viewspace-2154381/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ORACLE -詳解SCNOracle
- 【SCN】Oracle SCN 詳細介紹Oracle
- Oracle SCN機制詳細解讀Oracle
- Oracle:SCNOracle
- 【恩墨學院】深入剖析 - Oracle SCN機制詳細解讀Oracle
- 【SCN】Oracle推薦scn命令參考Oracle
- 【SCN】Oracle檢查scn值指令碼Oracle指令碼
- oracle的scn及sequenceOracle
- Oracle 檢查點涉及的SCNOracle
- Oracle的SCN顯示問題Oracle
- ordebug 手動修改Oracle sga scnOracle
- oracle基於SCN增量恢復Oracle
- Oracle SCN健康狀態檢查Oracle
- Oracle的DBMS_SCN修正以及SCN的auto-rollover新特性Oracle
- 深入瞭解SCN(轉)
- oracle rowid詳解Oracle
- oracle 推進scn(poke、gdb、event、bbed)方法Oracle
- ORACLE的HINT詳解Oracle
- Oracle練習詳解Oracle
- oracle oradebug使用詳解Oracle
- ORACLE基礎之oracle鎖(oracle lock mode)詳解Oracle
- Oracle資料庫中的多種SCN彙總Oracle資料庫
- oracle: default role 詳解(轉)Oracle
- Oracle中job的使用詳解Oracle
- 一、oracle 高水位線詳解Oracle
- Oracle GoldenGate常用引數詳解OracleGo
- oracle rac 核心引數詳解Oracle
- Oracle中pivot函式詳解Oracle函式
- 【RECYCLEBIN】Oracle回收站詳解Oracle
- oracle 密碼詳解以及破解Oracle密碼
- oracle連線查詢詳解Oracle
- Oracle的表空間quota詳解Oracle
- 詳解oracle資料庫閃回Oracle資料庫
- 【kingsql分享】使用BBED修改Oracle資料檔案頭推進SCNSQLOracle
- 【INDEX】Oracle分割槽索引技術詳解IndexOracle索引
- 【DATAGUARD】Oracle Dataguard體系架構詳解Oracle架構
- ORACLE中Cursor_sharing引數詳解Oracle
- Oracle minus用法詳解及應用例項Oracle