【聽海日誌】之SCN與Oracle

聽海★藍心夢發表於2012-04-12

一、SCN基礎

1、什麼是SCN

Concepts中是這樣描述SCN的:

A system change number (SCN) is a logical, internal timestamp used by Oracle Database. SCNs order events that occur within the database, which is necessary to satisfy the ACID properties of a transaction. Oracle Database uses SCNs to mark the SCN before which all changes are known to be on disk so that recovery avoids applying unnecessary redo. The database also uses SCNs to mark the point at which no redo exists for a set of data so that recovery can stop.

怎麼理解這個“SCN(系統變更號)是供Oracle資料庫使用的一個邏輯的、內部的時間戳”呢?要理解這個先需要理解Oracle中的事務(Transaction)和資料一致性(Data Consistency)的概念。

先說說資料一致性的概念。資料一致性指的是資料的可用性。比如說管理一個財務的系統,需要從A賬戶將100元轉入到B賬戶,正常的操作是從A賬戶減去100元,然後給B賬戶加上100元,如果這兩步操作都正常完成了,那我們可以說完成轉賬操作之後的資料是一致可用的;但是如果在操作的過程中出了問題,A賬戶的100元給減掉了,但是B賬戶卻沒有加上100元,這樣的情況下產生的結果資料就有問題了,因為部分操作的失敗導致了資料的不一致而不可用,在實際中肯定是要避免這種讓資料不一致的情況發生的。在Oracle資料庫中,保證資料一致性的方法就是事務。

事務是一個邏輯的、原子性的作業單元,通常由一個或者是多個SQL組成,一個事務裡面的所有SQL操作要麼全部失敗回滾(Rollback),要麼就是全部成功提交(Commit)。就像上面轉賬的例子,為保證資料的一致性,就需要將轉賬的兩步操作放在一個事務裡面,這樣不管哪個操作失敗了,都需要將所有已進行的操作回滾,以保證資料的可用性。進行事務管理是資料庫區別於別的檔案系統的一個最主要的特徵,在資料庫中事務最主要的作用就是保證了資料的一致性,每次事務的提交都是將資料庫從一種一致性的狀態帶入到另外一種一致性的狀態中,SCN就是用來對資料庫的每個一致狀態進行標記的,每當資料庫進入到一個新的一致的狀態,SCN就會加1,也就是每個提交操作之後,SCN都會增加。也許你會想為什麼不直接記錄事務提交時候的時間戳呢?這裡面主要是涉及了兩個問題,一個是時間戳記錄的精度有限,再一個就是在分散式系統中記錄時間戳會存在系統時鐘同步的問題,詳細的討論可以檢視Ordering Events in Oracle

SCN在資料庫中是一個單一的不斷的隨著資料庫一致性狀態的改變而自增的序列。正如一個時間戳代表著時間裡面的某一個固定的時刻點一樣,每一個SCN值也代表著資料庫在執行當中的一個一致性的點,大的SCN值所對應的事務總是比小SCN值的事務發生的更晚。因此把SCN說成是Oracle資料庫的邏輯時間戳是很恰當的。

2SCN概述

SCN是當Oracle資料庫更新後,由DBMS去自動維護累積遞增的一個數字。通常看文章的時候能看到各種型別的SCN,但是嚴格來說SCN是沒有分類的,之所以會有不同型別的SCN並不是說這些SCN的概念不一樣,而是說不同分類的SCN代表的意義不一樣,不管什麼時候SCN所指代的都是資料庫的某個一致性的狀態。就像我們給一天中的某個時間點定義上班時間、另外的某個時間點定義成下班時間一樣,資料庫Checkpoint發生點的SCN被稱為Checkpoint SCN,僅此而已。Oracle資料庫中一共有4SCN分別為:

•系統檢查點SCN (System Checkpoint SCN)

•檔案檢查點SCN (Datafile Checkpoint SCN)

•結束SCN (Stop SCN)

•資料檔案頭SCN (Start SCN)

其中前面3SCN存在於控制檔案中,最後一種則存在於資料檔案的檔案頭中,在Oracle中用來標識資料庫的每一次改動,及其先後順序,SCN的最大值是0xffff.ffffffff。在控制檔案中,System Checkpoint SCN是針對整個資料庫全域性的,因而只存在一個,而Datafile Checkpoint SCNStop SCN是針對每個資料檔案的,因而一個資料檔案就對應在控制檔案中存在一份Datafile Checkpoint SCNStop SCN。在資料庫正常執行期間,Stop SCN(透過檢視v$datafile的欄位last_change#可以查詢)是一個無窮大的數字或者NULL

1、系統檢查點SCN

系統檢查點SCN位於控制檔案中,當檢查點程式啟動時(ckpt)Oracle就把系統檢查點的SCN儲存到控制檔案中。該SCN是全域性範圍的,當發生檔案級別的SCN時,例如將表空間置於只讀狀態,則不會更新系統檢查點SCN。查詢系統檢查點SCN的命令如下:

sys@ORCL> select CHECKPOINT_CHANGE# from v$database;

CHECKPOINT_CHANGE#

------------------

        21655892

2、檔案SCN

ckpt程式啟動時,包括全域性範圍的(比如日誌切換)以及檔案級別的檢查點(將表空間置為只讀、begin backup或將某個資料檔案設定為offline等),這時會在控制檔案中記錄的SCN。查詢資料檔案SCN的命令如下:

sys@ORCL> alter tablespace users read only;

Tablespace altered.

sys@ORCL> select file#,checkpoint_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE#

---------- ------------------

       1        21655892

       2        21655892

       3        21655892

       4        21657577

       5        21657577

       6        21655892

 

6 rows selected.

sys@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

        21655892

可以看到45號檔案也就是users表空間所屬的檔案SCN值和其他檔案不一致,且比系統檢查點的SCN要大(因為這兩個資料檔案最後被操作,其他資料檔案沒有變動)

3、結束SCN

每個資料檔案都有一個結束SCN,在資料庫的正常執行中,只要資料檔案線上且是可讀寫的,結束SCNNULL。否則則存在具體的SCN值。結束SCN也記錄在控制檔案中。

sys@ORCL> select TABLESPACE_NAME,STATUS from dba_tablespaces;

TABLESPACE_NAME              STATUS

------------------------------ ----------------

SYSTEM                         ONLINE

SYSAUX                         ONLINE

UNDOTBS1                    ONLINE

TEMP                        ONLINE

USERS                            READ ONLY

sys@ORCL> select file#,LAST_CHANGE# from v$datafile;        

     FILE# LAST_CHANGE#

---------- ------------

       1

       2

       3

       4     21657577

       5     21657577

       6

 

6 rows selected.

可以看到除了users表空間的結束SCN不為空,其他資料檔案的結束SCN為空。將資料庫至於mount狀態,由於該狀態下所有的資料檔案都不可寫,故mount狀態下所有的資料檔案都具有結束SCN

sys@ORCL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

sys@ORCL> startup mount

ORACLE instance started.

 

Total System Global Area  263049216 bytes

Fixed Size              2212448 bytes

Variable Size               230690208 bytes

Database Buffers         25165824 bytes

Redo Buffers                4980736 bytes

Database mounted.

sys@ORCL> select file#,last_change# from v$datafile;

 

     FILE# LAST_CHANGE#

---------- ------------

       1     21657939

       2     21657939

       3     21657939

       4     21657577

       5     21657577

       6     21657939

 

6 rows selected.

4、資料檔案頭SCN

不同於上述的SCN資料檔案開始SCN記錄在每個資料檔案中。當發生系統及檔案級別的檢查點後,不僅將這時的SCN號記錄在控制檔案中,同樣也記錄在資料檔案中。查詢資料檔案頭SCN的命令如下:

sys@ORCL> select file#,CHECKPOINT_CHANGE# from v$datafile_header;

 

FILE# CHECKPOINT_CHANGE#

---------- ------------------

       1        21657939

       2        21657939

       3        21657939

       4        21657577

       5        21657577

       6        21657939

 

6 rows selected.

3SCN相關概念

1Redo log中的high SCNlow SCN

OracleRedo log會順序紀錄資料庫的各個變化。一組redo log檔案寫滿後,會自動切換到下一組redo log檔案。則上一組redo loghigh SCN就是下一組redo loglow SCN。在current loghigh SCN為無窮大。可透過查詢v$log_history檢視 low SCN high SCN

sys@ORCL> select recid,sequence#,first_change#,next_change# from v$log_history;

     RECID SEQUENCE# FIRST_CHANGE#      NEXT_CHANGE#

---------- --------- ------------- --------------------

       1      2      21,069,995        21,085,568

       2      1      21,085,569        21,105,418

       3      2      21,105,418        21,132,018

       4      3      21,132,018        21,163,953

       5      4      21,163,953        21,191,900

       6      5      21,191,900        21,209,347

       7      6      21,209,347        21,223,812

       8      7      21,223,812       21,232,963

       9      8      21,232,963        21,263,223

      10      9      21,263,223        21,288,586

      11     10      21,288,586        21,301,971

      12      1      21,300,115        21,324,025

      13      2      21,324,025        21,344,131

      14      3      21,344,131        21,347,920

      15      4      21,347,920        21,369,784

      16      5      21,369,784        21,374,509

      17      6      21,374,509        21,374,914

      18      7      21,374,914        21,375,336

      19      8      21,375,336        21,384,136

      20      9      21,384,136        21,409,089

      21     10      21,409,089        21,446,217

      22     11      21,446,217        21,496,982

      23     12      21,496,982        21,509,283

      24     13      21,509,283        21,545,787

      25     14      21,545,787        21,564,418

      26     15      21,564,418        21,581,068

      27     16      21,581,068        21,582,611

      28     17      21,582,611        21,582,860

      29     18      21,582,860        21,583,942

      30     19      21,583,942        21,609,862

      31     20      21,609,862        21,630,988

      32     21      21,630,988        21,655,891

 

32 rows selected.

2、檢視currnet redolog中的high SCN

sys@ORCL> select vf.member,v.status,v.first_change# from v$logfile vf,v$log v where vf.group#=v.group# and v.status='CURRENT';

MEMBER                                 STATUS         FIRST_CHANGE#

------------------------------------------------------------------------------------------------------------------

/opt/oracle/oradata/orcl/redo01.log              CURRENT        21,655,891

sys@ORCL> alter system dump logfile '/opt/oracle/oradata/orcl/redo01.log';

System altered.

sys@ORCL> show parameter user_dump

NAME                      TYPE  VALUE

------------------------------------ ----------- ------------------------------

user_dump_dest          string /opt/oracle/diag/rdbms/orcl/orcl/trace

開啟轉儲出來的檔案,可以看到:

DUMP OF REDO FROM FILE '/opt/oracle/oradata/orcl/redo01.log'

 Opcodes *.*

 RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff

 SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff

 Times: creation thru eternity

 FILE HEADER:

      Compatibility Vsn = 186646528=0xb200000

      Db ID=1284637334=0x4c920296, Db Name='ORCL'

      Activation ID=1296530476=0x4d477c2c

      Control Seq=19392=0x4bc0, File size=102400=0x19000

      File Number=1, Blksiz=512, File Type=2 LOG

 descrip:"Thread 0001, Seq# 0000000022, SCN 0x0000014a7153-0xffffffffffff"

 thread: 1 nab: 0xffffffff seq: 0x00000016 hws: 0x5 eot: 1 dis: 0

 resetlogs count: 0x2dd248e0 scn: 0x0000.01450393 (21300115)

 prev resetlogs count: 0x2dce6ef7 scn: 0x0000.0141bd81 (21085569)

 Low  scn: 0x0000.014a7153 (21655891) 03/20/2012 09:18:56

 Next scn: 0xffff.ffffffff 01/01/1988 00:00:00

 Enabled scn: 0x0000.01450393 (21300115) 12/01/2011 15:18:56

 Thread closed scn: 0x0000.014a7953 (21657939) 03/20/2012 09:43:56

 Disk cksum: 0x202e Calc cksum: 0x202e

 Terminal recovery stop scn: 0x0000.00000000

 Terminal recovery  01/01/1988 00:00:00

 Most recent redo scn: 0x0000.00000000

 Largest LWN: 0 blocks

 End-of-redo stream : No

 Unprotected mode

 Miscellaneous flags: 0x800000

 Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000

redo log中當前系統的SCN記錄當前最新的資料庫SCN值可透過如下命令檢視:

sys@ORCL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

------------------------

             21658581

如果需要進行例項恢復,則需恢復的記錄為2165589121658581redo log中的記錄。

3、日誌切換或者checkpoint

當日志切換或發生checkpoint時,從Low SCNNext 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都不會被更新。

4、心跳

Oracle中有一個事件叫Heartbeat,這個詞在很多地方被提及,並且有著不同的含義(比如RAC),我們這裡要討論的是CKPTHeartbeat機制。Oracle透過CKPT程式每3秒將Heartbeat寫入控制檔案,以減少故障時的恢復時間。

5、資料庫正常關閉啟動

資料庫正常關閉時,系統會執行一個完全檢查點動作,並用該檢查點時的SCN號更新上述4SCN號,這時所有資料檔案的終止SCN號會設定為資料檔案頭的那個啟動SCN(除了離線和只讀的資料檔案)。

資料庫重新啟動時,Oracle將資料檔案頭中的啟動SCN與資料檔案檢查點SCN比較,如果這兩個值匹配,Oracle接下來再比較資料檔案頭中的SCN和控制檔案中資料檔案的終止SCN,如果這個值也匹配,就意味著所有資料塊已經提交,因此資料庫不需要進行恢復,此時資料庫直接開啟。當所有的資料檔案都開啟之後,線上且可讀寫的資料檔案終止SCN再次被設定為NULL,表示資料檔案已經開啟並能夠正常使用了。有些表空間是隻讀的,這時控制檔案中的系統檢查點SCN號會不斷增長,而資料檔案SCN號和檔案頭中的啟動SCN(會停止更新直到表空間又設定為可讀寫),顯然這時系統檢查點SCN號會大於資料檔案SCN和檔案頭啟動SCN

6、資料庫非正常關閉

資料庫非正常關閉(或稱為例項崩潰)時,終止SCN不會被設定,依然為NULL,這可以透過把資料庫啟動至mount狀態查詢出來。這樣重新啟動時,SMON程式會執行例項恢復工作,即先執行前滾,再把資料庫開啟,最後執行回滾操作。

7、資料檔案介質故障

出現介質故障時,資料檔案檢查點SCN及系統檢查點SCN比檔案頭啟動SCN大。系統發生介質故障時,資料檔案被以前的備份代替,控制檔案中的資料檔案檢查點SCN肯定比檔案頭中的啟動SCN要大,這樣Oracle就知道要對這個檔案進行介質恢復。

8、控制檔案介質故障

系統檢查點SCN及資料檔案SCN比資料檔案頭啟動SCN小:

在資料庫恢復時,控制檔案可能不是最新的,即把一個較早的控制檔案還原為當前的控制檔案,然後再執行恢復操作,這時控制檔案中的系統檢查點SCN和資料檔案SCN可能比檔案頭的啟動SCN小。這時恢復資料庫要用下面命令:recover database using Backup Controlfile或其他的恢復語句。

9、備份時的例項崩潰

當執行begin backup時例項崩潰:控制檔案中的資料檔案檢查點SCN號和資料檔案頭部檢查點SCN號相同,但是每個可讀寫的線上資料檔案之間檢查點SCN號不同,那麼要求介質恢復,例如發出begin backup命令後就會出現這種情況,需要透過end backup命令好才可以開啟資料庫。

4SCN檢視與轉換

1、檢視系統當前的SCN

Oracle資料庫提供了兩種直接檢視系統當前SCN的方法,一個是V$DATABASE中的CURRENT_SCN列,另外一個就是透過dbms_flashback.get_system_change_number得到。

sys@ORCL> col SCN for 9999999999999

sys@ORCL> SELECT current_SCN SCN FROM v$database;

         SCN

--------------

      21660463

sys@ORCL> SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER SCN FROM DUAL;

         SCN

--------------

      21660479

如果你好奇心足夠的話也許會執行下面的語句,然後發現一個“驚訝”的結果:

sys@ORCL> col SCN for 9999999999999

sys@ORCL> col SCN2 for 9999999999999

sys@ORCL> SELECT current_SCN SCN,DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER SCN2 FROM v$database;

         SCN              SCN2

-------------- --------------

      21660533           21660534

不過請不要驚訝,這個很正常,畢竟語句的執行時需要時間的,雖然很短,不過還是能發生很多的事情。

2SCN與時間的相互轉換

一個SCN值總是發生在某一個特定的時刻的,只不過由於粒度的不一樣,通常會存在多個SCN對應同一個時間戳。Oracle中提供了兩個函式以供我們進行SCN和時間的互換:

SCN_TO_TIMESTAMP(SCN_number) SCN轉換成時間戳。

TIMESTAMP_TO_SCN(timestamp) 將時間戳轉換成SCN

下面就舉幾個例子來說明:

SCN轉換成時間戳

sys@ORCL> SELECT SCN_TO_TIMESTAMP(21660534) timestamp FROM DUAL;

TIMESTAMP

---------------------------------------------------------------------------

20-3 -12 10.38.32.000000000 上午   -- 將時間戳轉換成

sys@ORCL> SELECT TIMESTAMP_TO_SCN(TO_TIMESTAMP('20-3-12 10.38.32.000000000','DD-Mon-RR HH:MI:SS.FF A.M.')) SCN FROM DUAL;

         SCN

--------------

      2 1660533

很明顯的能看到同樣的時間戳,轉換出來的SCN就是不一樣,其根本原因就是粒度問題了。

3ORA_ROWSCN偽列

10g開始,Oracle提供了一個名為ORA_ROWSCN的偽列來讓我們更近距離的接觸SCN這個東西,利用這個偽列能很清楚的觀察提交(Commit)操作對於表中SCN的影響。

我們先來建立以下測試的資料表和資料(例子延伸自《Oracle9i & 10g程式設計藝術》一書),下面的例子進行兩次,兩次唯一的不同在於建表時引數不一樣,我們透過這個來觀察SCN記錄的一些行為。

試驗一:

建立表

test@ORCL> CREATE TABLE t (x INT);

Table created.

插入資料

test@ORCL> BEGIN FOR i IN 1 .. 5 LOOP

INSERT INTO t VALUES(i );

COMMIT;

END LOOP;

END;

/

檢視結果

SYS@ORCL> SELECT x, ORA_ROWSCN SCN,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCKNO FROM t ORDER BY 2;

       X        SCN    BLOCKNO

---------- -------------- ----------

       1   21661219     146911

       2   21661219     146911

       5   21661219     146911

       4   21661219     146911

       3   21661219     146911

試驗二:

建立表

test@ORCL> CREATE TABLE t (x INT) ROWDEPENDENCIES;

Table created.

插入資料

test@ORCL> BEGIN FOR i in 1 .. 5 LOOP

INSERT INTO t VALUES (i);

COMMIT;

END LOOP;

END;

/

檢視結果

test@ORCL> SELECT x, ORA_ROWSCN SCN, DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) blockno FROM t ORDER BY 2;

       X        SCN    BLOCKNO

---------- -------------- ----------

       1   21661327     146919

       2   21661329     146919

       3   21661330     146919

       4   21661332     146919

       5   21661334     146919

試驗一中每行資料的SCN資料都是一樣的,如果根據我們現在對SCN的理解的話每次提交之後SCN應該變化才對的,那問題出在哪裡呢?問題就出在預設情況下Oracle資料庫記錄SCN是以資料庫為單位記錄的,因為在資料庫讀取資料的時候都是以資料塊單位,而不是以行為單位的。

要想達到按行記錄SCN就必須在建立表的時候使用ROWDEPENDENCIES引數,ROWDEPENDENCIES用於開啟一個資料表的行級的追蹤,在行級維護SCN記錄,使得我們能清楚的看到每次提交操作對於SCN的影響。試驗二就是使用表的ROWDEPENDENCIES特性之後的結果。

注:ROWDEPENDENCIES有個重要的作用是用來實現樂觀鎖定(Optimistic Locking),這個在《Oracle9i & 10g程式設計藝術》一書中有詳細的描述。

5SCN的作用

SCN描述的是資料一致性的狀態,自然的它就會在各種涉及資料一致性的場合中起到重要作用的,下面列舉的就是其中的一部分:

 •讀資料的一致性

 •資料庫恢復

 •Flashback

 •Stream

 •等等其他的

說這個的原因就是想說SCNOracle中的應用無處不在,理解SCN是理解資料庫許多其他功能工作原理的基礎。

在資料庫啟動過程中,當System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN號都相同時,資料庫可以正常啟動,不需要做media recovery。三者當中有一個不同時,則需要做media recovery。

如果在啟動的過程中,End SCN號為NULL,則需要做instance recovery。這種情況一般是資料庫不正常關閉導致。ORACLE在啟動過程中首先檢查是否需要media recovery,然後再檢查是否需要instance recovery。

二、SCN機制解析

1、事務中的SCN

SCNSystem Chang Number)作為oracle中的一個重要機制,在資料恢復、Data GuardStreams複製、RAC節點間的同步等各個功能中起著重要作用。理解SCN的運作機制,可以幫助你更加深入地瞭解上述功能。在理解SCN之前,我們先看下oracle事務中的資料變化是如何寫入資料檔案的:

1、事務開始;

2、在buffer cache中找到需要的資料塊,否則,從資料檔案中載入buffer cache中;

3、事務修改buffer cache的資料塊,該資料被標識為“髒資料”,並被寫入log buffer中;

4、事務提交,LGWR程式將log buffer中的“髒資料”寫入redo log file中;

5、當發生checkpointCKPT程式更新所有資料檔案的檔案頭中的資訊,DBWn程式則負責將Buffer Cache中的髒資料寫入到資料檔案中。

經過上述5個步驟,事務中的資料變化最終被寫入到資料檔案中。但是,一旦在上述中間環節時,資料庫意外當機了,在重新啟動時如何知道哪些資料已經寫入資料檔案、哪些沒有寫呢(同樣,在DGstreams中也存在類似疑問:redo log中哪些是上一次同步已經複製過的資料、哪些沒有)?SCN機制就能比較完善的解決上述問題。SCN是一個數字,確切的說是一個只會增加、不會減少的數字。正是它這種只會增加的特性確保了Oracle知道哪些應該被恢復、哪些應該被複制。

在一個事務提交後(上述第四個步驟),會在redo log中存在一條redo記錄,同時,系統為其提供一個最新的SCN(透過函式dbms_flashback.get_system_change_number可以知道當前的最新SCN),記錄在該條記錄中。如果該條記錄是在redo log被清空(日誌滿做切換時或發生checkpoint時,所有變化日誌已經被寫入資料檔案中),則其SCN被記錄為redo loglow SCN。以後在日誌再次被清空前寫入的redo記錄中SCN則成為Next SCN

當日志切換或發生checkpoint(上述第五個步驟)時,從Low SCNNext 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都不會被更新。

2、產生最新的SCN

實際上,這個數字是由當時的timestamp轉換過來的。每當需要產生一個最新的SCNredo記錄時,系統獲取當時的timestamp,將其轉換為數字作為SCN。我們可以透過函式SCN_TO_TIMESTAMP10g以後)將其轉換回timestamp

test@ORCL> select dbms_flashback.get_system_change_number get_scn, SCN_TO_TIMESTAMP(dbms_flashback.get_system_change_number) scn_to_timestamp from dual;

   GET_SCN SCN_TO_TIMESTAMP

---------- ---------------------------------------------------------------------------

  21662602 20-3 -12 11.21.47.000000000 上午

也可以用函式timestamp_to_scn將一個timestamp轉換為SCN

test@ORCL> select timestamp_to_scn(SYSTIMESTAMP) as SCN from dual;

         SCN

--------------

      21662618

最後,SCN除了作為反映事務資料變化並保持同步外,它還起到系統的“心跳”作用——每隔3秒左右系統會重新整理一次系統SCN

3SCN在資料庫恢復中的作用

資料庫在正常關閉(shutdown immediate/normal)時,會先做一次checkpoint,將log file中的資料寫入資料檔案中,將控制檔案、資料檔案中的SCN(包括控制檔案中的Stop SCN)都更新為最新的SCN

資料庫異常/意外關閉不會或者只更新部分Stop SCN

當資料庫啟動時,Oracle先檢查控制檔案中的每個Datafile Checkpoint SCN和資料檔案中的Start SCN是否相同,再檢查每個Datafile Checkpoint SCNStop SCN是否相同。如果發現有不同,就從Redo Log中找到丟失的SCN,重新寫入資料檔案中進行恢復。

SCN作為Oracle中的一個重要機制,在多個重要功能中起著“控制器”的作用。瞭解SCN的產生和實現方式,幫助DBA理解和處理恢復、DGStreams複製的問題。

利用SCN機制,在Oracle10g11g中又增加了一些很實用的功能——資料庫閃回、資料庫負載重現等。

1、使用using backup controlfile

1)使用備份控制檔案。

2)重建resetlogs控制檔案,如果重建noresetlogs不必要使用using backup controlfile

2alter database open resetlog

指定RESETLOGS將重設當前LOG sequence number1,拋棄所有日誌資訊。以下條件需要使用resetlog

1)在不完全恢復(介質恢復)。

2)使用備份控制檔案。

使用resetlogs開啟資料庫後務必完整地備份一次資料庫。

3create controlfile resetlogs/noresetlogs

1)用Noresetlogs重建控制檔案時,控制檔案中datafile Checkpoint來自Online logs中的Current log頭。

2)用Resetlogs重建控制檔案時,控制檔案中datafile Checkpoint來自各資料檔案頭。

system SCN,datafile SCN,start SCN不全相等,需要介質恢復,如果stopSCN NULL需要例項恢復resetlogs拋棄所有在上一次恢復沒有用到的日誌資訊,確保不被重新用與恢復。

4、各種異常情況需要的恢復

系統正常關閉:

system SCN=datafile SCN=start SCN=stop SCN

1) system SCN=datafile SCN=start SCN,不需要介質恢復。

2) stopSCN not NULL,不需要例項恢復。

系統異常關閉:

system SCN=datafile SCN=start SCNstop SCN NULL

1) system SCN=datafile SCN=start SCN,不需要介質恢復

2) stopSCN NULL,需要例項恢復

舊資料檔案:

system SCN=datafile SCN>start SCNstop SCN NULL/notNULL

1) system SCN=datafile SCN>start SCN,需要介質恢復成system SCN=datafile SCN=start SCN

2) stopSCN NULL,需要例項恢復,not NULL不需要例項恢復。

備份控制檔案:

system SCN=datafile SCN<=start SCN(當資料檔案為舊的相等)stop SCN notNULL/NULL

1) system SCN=datafile SCN<=start SCN,需要使用using backup controlfile介質恢復成system SCN=datafile SCN=start SCN=current log SCN(當前日誌最大SCN)

2) 為保證上一次恢復沒有用到log日誌不被使用,必須resetlogs

重建noresetlogs控制檔案:

控制檔案中 datafile Checkpoint來自Online logs中的Current log頭。

current log SCN=system SCN=datafile SCN>=start SCN,stop SCN not NULL/NULL

1) current log SCN=system SCN=datafile SCN>=start SCN,需要介質恢復成system SCN=datafile SCN=start SCN=redolog SCN(當前日誌最大SCN),stop SCN not NULL

2) stopSCN not NULL 不需要例項恢復。

重建resetlogs控制檔案:

控制檔案中datafile Checkpoint來自各資料檔案頭。

system SCN>=datafile SCN=start SCN,stop SCN not NULL/NULL

1) system SCN>=datafile SCN=start SCN,需要使用using backup controlfile介質恢復成system SCN=datafile SCN=start SCN(當前日誌最大SCN),stop SCN not NULL

2) stop notNULL,因為SCN已經為redolog SCNlog已經不能使用,必須resetlogs

三、Oracle SCN研究

1SCN的管理方式

OracleSCN的管理,分為單節點和RAC兩種方式。

1、單節點的instance

單節點的instance中,SCN值存在SGA區,由system commit number latch保護。任何程式要得到當前的SCN值,都要先得到這個latch

2RAC/OPS環境中

Oracle透過排隊機制(Enqueue)實現SCN在各並行節點之間的順序增長。具體有兩種方法:

Lamport演算法:又稱麵包房演算法,先來先服務演算法。跟很多銀行採用的排隊機制一樣。客戶到了銀行,先領取一個服務號。一旦某個視窗出現空閒,擁有最小服務號的客戶就可以去空閒視窗辦理業務。

Commit廣播演算法:一有commit完成,最新的SCN就廣播到所有節點中。

上述兩種演算法可以透過調整初始化引數max_commit_propagation_delay來切換。在多數系統(除了Compaq Tur64 Unix)中,該引數的預設值都是700釐秒(centisecond),採用Lamport演算法。如果該值小於100釐秒,Oracle就採用廣播演算法,並且記錄在alert.log檔案中。

2、幾種重要的SCN

1Commit SCN

當使用者提交commit命令後,系統將當前SCN賦給該transaction。這些資訊都反映在redo buffer中,並馬上更新到redo log檔案裡。

2Offline SCN

除了System tablespace以外的任何表空間,當我們執行alter tablespaceoffline normal;命令時,就會觸發一個checkpoint,將記憶體中的dirty buffer寫入磁碟檔案中。Checkpoint完成後,資料檔案頭會更新checkpoint SCNoffline normal SCN值。其中資料庫檔案頭的checkpoint SCN值可透過查詢列x$kccfe.fecps得到。

如果執行alter tablespaceoffline命令時採用temporaryimmediate選項,而不用normal選項時,offline normal SCN會被設成0。這樣當資料庫重啟後透過resetlog方式開啟時,該表空間就無法再改回線上狀態。

3Checkpoint SCN

當資料庫記憶體的髒資料塊(dirty blocks)寫到各資料檔案中時,就發生一次checkpoint。資料庫的當前checkpoint SCN值存在x$kccdi.diSCN中。Checkpoint SCN在資料庫恢復中起著至關重要的作用。無論你用何種辦法恢復資料庫,只有當各個資料庫檔案的checkpoint SCN都相同時,資料庫才能開啟。

雖然引數“_allow_resetlogs_corruption”可以在checkpoint SCN不一致時強制開啟資料庫,但是這樣的資料庫在open後必須馬上作全庫的export,然後重建資料庫並import資料。

4Resetlog SCN

資料庫不完全恢復時,在指定時間點後的SCN都無法再應用到資料庫中。Resetlog時的SCN就被設成當前資料庫SCNredo log也會被重新設定。

5Stop SCN

Stop SCN記錄在資料檔案頭上。當資料庫處在開啟狀態時,stop SCN被設成最大值0xffff.ffffffff。在資料庫正常關閉過程中,stop SCN被設定成當前系統的最大SCN值。在資料庫開啟過程中,Oracle會比較各檔案的stop SCNcheckpoint SCN,如果值不一致,表明資料庫先前沒有正常關閉,需要做恢復。

6High and Low SCN

OracleRedo log會順序紀錄資料庫的各個變化。一組redo log檔案寫滿後,會自動切換到下一組redo log檔案。則上一組redo loghigh SCN就是下一組redo loglow SCN

在檢視v$log_history中,sequence#代表redo log的序列號,first_change#表示當前redo loglow SCN,列next_change#表示當前redo loghigh SCN

test@ORCL> col recid format 9999

test@ORCL> col requence# format 9999

test@ORCL> col first_change# format 9,999,999,999,999

test@ORCL> col next_change# format 9,999,999,999,999

test@ORCL> select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;

RECID SEQUENCE#      FIRST_CHANGE#  NEXT_CHANGE#

----- --------- ------------------ ------------------

    1         2      21,069,995      21,085,568

    2         1      21,085,569      21,105,418

    3         2      21,105,418      21,132,018

    4         3      21,132,018      21,163,953

    5         4      21,163,953      21,191,900

3SCNoracle資料庫恢復的關係

SCN號與oracle資料庫恢復過程有著密切的關係,只有很好地理解了這層關係,才能深刻地理解恢復的原理,從而才能很好地解決這方面的問題。

CKPT程式在checkpoint發生時,將當時的SCN號寫入資料檔案頭和控制檔案,同時通知DBWR程式將資料塊寫到資料檔案。CKPT程式也會在控制檔案中記錄RBA(redo byte address),以標誌Recovery需要從日誌中哪個地方開始。

1SCN不連續原因

1) 當發生日誌組切換的時候。

2) 當符合LOG_CHECKPOINT_TIMEOUTLOG_CHECKPOINT_INTERVALfast_start_io_target,fast_start_mttr_target引數設定的時候。

3) 當執行ALTER SYSTEM SWITCH LOGFILE的時候。

4) 當執行ALTER SYSTEM CHECKPOINT的時候。

5) 當執行alter tablespace XXX begin backupend backup的時候。

6) 當執行alter tablespace ,datafile offline的時候。

2SCN與資料庫啟動

在資料庫啟動過程中,當System Checkpoint SCNDatafile Checkpoint SCNStart SCN號都相同時,資料庫可以正常啟動,不需要做media recovery.三者當中有一個不同時,則需要做media recovery。如果在啟動的過程中,End SCN號為NULL,則需要做instance recoveryORACLE在啟動過程中首先檢查是否需要media recovery,然後再檢查是否需要instance recovery

3SCN與資料庫關閉

如果資料庫的正常關閉的話,將會觸發一個checkpoint,同時將資料檔案的END SCN號設定為相應資料檔案的Start SCN號。當資料庫啟動時,發現它們是一致的,則不需要做instance recovery。在資料庫正常啟動後,ORACLE會將END SCN號設定為NULL。如果資料庫異常關閉的話,則END SCN號將為NULL

為什麼需要System checkpoint SCN號與Datafile Checkpoint SCN號?為什麼ORACLE會在控制檔案中記錄System checkpoint SCN號的同時,還需要為每個資料檔案記錄Datafile Checkpoint SCN號?

原因有二:

1) 對只讀表空間,其資料檔案的Datafile Checkpoint SCNStart SCNEND SCN號均相同。這三個SCN在表空間處於只讀期間都將被凍結。

2) 如果控制檔案不是當前的控制檔案,則System checkpoint會小於Start SCNEND SCN號。記錄這些SCN號,可以區分控制檔案是否是當前的控制檔案。

4Recovery database using backup controlfile

當有一個Start SCN號超過了System Checkpoit SCN號時,則說明控制檔案不是當前的控制檔案,因此在做recovery時需要採用using backup controlfile。這是為什麼需要記錄SystemCheckpoint SCN的原因之一。

這裡需要一提的是,當重建控制檔案的時候,System Checkpoint SCN0Datafile Checkpoint SCN的資料來自於Start SCN。根據上述的描述,此時需要採用using backup controlfilerecovery

重建控制檔案方式分兩種(resetlogsnoresetlogs):

1) 使用resetlogs選項時,System Checkpoint SCN為被歸為0,而其中記錄的各個資料檔案的Datafile Checkpoint SCN則來自於Start SCN(也就是說可能會從冷備份的資料檔案的資料檔案頭中獲取)。根據上述的描述,此時需要採用using backup controlfilerecovery.因此情況是System Checkpoint SCN=0 < Start SCN = Datafile Checkpoint SCN

2) 使用noresetlogs選項時,有一個前提就是:一定要有online redo log的存在。否則就要使用resetlogs選項。這個時候控制檔案重建好時,其system checkpoint SCN=Datafile Checkpoint SCN=Lastest Checkpoint SCN in online redo log,我們可以看到Datafile Checkpoint SCN並沒有從Start SCN中讀取。而是讀取了最新的日誌檔案中的SCN作為自己的資料。此時重建的控制檔案在恢復中的作用跟最新的控制檔案類似,System Checkpoint SCN(已經讀取最新的redo logcheckpoint SCN資訊)可能會>Start SCN(因為資料檔案可能會從冷備份中恢復),恢復時就不需要加using backup controlfile子句了。

關於backup controlfile的補充:

backup controlfile只有備份時刻的archive log資訊,並沒有DB crash時刻的archive log資訊,所以並不會自動應用online redo log,而是提示找不到序號為Lastest Archive log sequence + 1archive log。儘管你可以手動指定online redo log來實現完全恢復,但因為一旦使用了using backup controlfile子句,Oracle就視為不完全恢復,必須open resetlogs。實際上,假如你有舊的控制檔案又不想resetlogs,那很簡單,使用舊的控制檔案mount然後backup to trace,然後手工建立控制檔案,使用reuse database ... noresetlogs這樣就可以recover database自動恢復並open database而不用resetlogs(切記:必須有所有的online redo logs才可以這樣!)。備份的控制檔案不能自動進行完全恢復,可以手工apply日誌進行完全恢復。

5、重建自動進行完全恢復示例

背景:

Oracle 11.2.0.1.0

Linux Enterprise RedHat 5

採用rman做熱備,在備份期間,做不少事務,同時做alter system checkpoint

[oracle@localhost software]$ rman target /

Recovery Manager: Release 11.2.0.1.0 - Production on 星期二 3 20 15:15:38 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

connected to target database: ORCL (DBID=1284637334)

RMAN> run {

2> allocate channel c1 type disk;

3> backup database filesperset 3 format '/software/full_%p_%t.bak';

4> release channel c1;

5> }

allocated channel: c1

channel c1: SID=35 device type=DISK

 

Starting backup at 20-3 -12

channel c1: starting compressed full datafile backup set

channel c1: specifying datafile(s) in backup set

input datafile file number=00005 name=/home/oracle/oradata/users02.dbf

input datafile file number=00001 name=/opt/oracle/oradata/orcl/system01.dbf

input datafile file number=00003 name=/opt/oracle/oradata/orcl/undotbs01.dbf

channel c1: starting piece 1 at 20-3 -12

channel c1: finished piece 1 at 20-3 -12

piece handle=/software/full_1_778432785.bak tag=TAG20120320T151945 comment=NONE

channel c1: backup set complete, elapsed time: 00:02:57

channel c1: starting compressed full datafile backup set

channel c1: specifying datafile(s) in backup set

input datafile file number=00004 name=/home/oracle/oradata/users01.dbf

input datafile file number=00002 name=/home/oracle/oradata/sysaux01.dbf

input datafile file number=00006 name=/home/oracle/oradata/undotbs02.dbf

channel c1: starting piece 1 at 20-3 -12

channel c1: finished piece 1 at 20-3 -12

piece handle=/software/full_1_778432963.bak tag=TAG20120320T151945 comment=NONE

channel c1: backup set complete, elapsed time: 00:01:45

Finished backup at 20-3 -12

 

Starting Control File and SPFILE Autobackup at 20-3 -12

piece handle=/home/oracle/dbbackup/ctl_20120320_c-1284637334-20120320-02 comment=NONE

Finished Control File and SPFILE Autobackup at 20-3 -12

 

released channel: c1

注:在這個備份角本里面我們加了filesperset 3。這樣將整個資料庫分成兩個備份集。這樣還原出來的資料檔案其checkpoint_change#將不一樣。否則由於資料庫資料檔案不多,都將包含在一個備份集中,這樣即使在備份中做insert操作和alter system checkpoint也不會產生不同的checkpoint_change#。因為rman備份是將一個備份集中的檔案同時備份的。而checkpoint_change#是存放在資料檔案頭部的,這樣備份這些資料檔案的頭部的時間將是很快的。

然後模擬還原資料庫:

sys@ORCL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

sys@ORCL> startup mount;

ORACLE instance started.

Total System Global Area  263049216 bytes

Fixed Size              2212448 bytes

Variable Size               234884512 bytes

Database Buffers         20971520 bytes

Redo Buffers                4980736 bytes

Database mounted.

RMAN> run {

2> allocate channel c1 type disk;

3> restore database;

4> release channel c1;

5> }

using target database control file instead of recovery catalog

allocated channel: c1

channel c1: SID=21 device type=DISK

 

Starting restore at 20-3 -12

 

channel c1: starting datafile backup set restore

channel c1: specifying datafile(s) to restore from backup set

channel c1: restoring datafile 00001 to /opt/oracle/oradata/orcl/system01.dbf

channel c1: restoring datafile 00003 to /opt/oracle/oradata/orcl/undotbs01.dbf

channel c1: restoring datafile 00005 to /home/oracle/oradata/users02.dbf

channel c1: reading from backup piece /software/full_1_778432785.bak

channel c1: piece handle=/software/full_1_778432785.bak tag=TAG20120320T151945

channel c1: restored backup piece 1

channel c1: restore complete, elapsed time: 00:02:27

channel c1: starting datafile backup set restore

channel c1: specifying datafile(s) to restore from backup set

channel c1: restoring datafile 00002 to /home/oracle/oradata/sysaux01.dbf

channel c1: restoring datafile 00004 to /home/oracle/oradata/users01.dbf

channel c1: restoring datafile 00006 to /home/oracle/oradata/undotbs02.dbf

channel c1: reading from backup piece /software/full_1_778432963.bak

channel c1: piece handle=/software/full_1_778432963.bak tag=TAG20120320T151945

channel c1: restored backup piece 1

channel c1: restore complete, elapsed time: 00:01:55

Finished restore at 20-3 -12

 

released channel: c1

sys@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

        21674485

sys@ORCL> select file#,checkpoint_change# from v$datafile;

  FILE#   CHECKPOINT_CHANGE#

----------    ------------------

       1        21674485

       2        21674485

       3        21674485

       4        21674485

       5        21674485

       6        21674485

6 rows selected.

sys@ORCL> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#

---------- ------------------

       1        21673534

       2        21673648

       3        21673534

       4        21673648

       5        21673534

       6        21673648

6 rows selected.

從這裡可以看出,顯然是需要做media recovery的。正常情況下,還需要做instance recovery。當然由於沒有線上日誌,所以只能做resetlogs

1) 有歸檔日誌存

若有歸檔日誌在,則只需要做一個recover database until cancel;然後即可alter database open resetlogs;

sys@ORCL> recover database until cancel;

ORA-00279: 更改 21673534 ( 03/20/2012 15:19:46 生成) 對於執行緒 1 是必需的

ORA-00289: 建議: /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_22_7pjh1ss0_.arc

ORA-00280: 更改 21673534 (用於執行緒 1) 在序列 #22

Specify log: {=suggested | filename | AUTO | CANCEL}

auto

ORA-00279: 更改 21674803 ( 03/20/2012 16:13:45 生成) 對於執行緒 1 是必需的

ORA-00289: 建議: /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_23_7pjh1vz3_.arc

ORA-00280: 更改 21674803 (用於執行緒 1) 在序列 #23

ORA-00278: 此恢復不再需要日誌檔案 '/opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_22_7pjh1ss0_.arc'

ORA-00279: 更改 21674806 ( 03/20/2012 16:13:47 生成) 對於執行緒 1 是必需的

ORA-00289: 建議: /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_24_7pjh1z5h_.arc

ORA-00280: 更改 21674806 (用於執行緒 1) 在序列 #24

ORA-00278: 此恢復不再需要日誌檔案 '/opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_23_7pjh1vz3_.arc'

ORA-00279: 更改 21674809 ( 03/20/2012 16:13:51 生成) 對於執行緒 1 是必需的

ORA-00289: 建議: /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_25_%u_.arc

ORA-00280: 更改 21674809 (用於執行緒 1) 在序列 #25

ORA-00278: 此恢復不再需要日誌檔案 '/opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_24_7pjh1z5h_.arc'

ORA-00308: 無法開啟歸檔日誌 '/opt/oracle/flash_recovery_area/ORCL/archivelog/2012_03_20/o1_mf_1_25_%u_.arc'

ORA-27037: 無法獲得檔案狀態

Linux-x86_64 Error: 2: No such file or directory

Additional information: 3

sys@ORCL> alter database open resetlogs;

Database altered.

2) 無歸檔日誌

如果沒有歸檔日誌,由於restore出來是沒有線上日誌的。如果v$datafile_headercheckpoint_change#是相同的,此時由於控制檔案中checkpoint_change#比資料檔案頭中要高,所以資料庫還是需要做media recovery

此時重建控制檔案還是一樣的,因為重建控制檔案後,在控制檔案中checkpoint_change#0,與檔案頭的checkpoint_change#還是不一樣,還需要media recovery。且由於控制檔案中checkpoint_change#比檔案頭中要高,所以做recover時還需要加上using backup controlfile

注:這時由於沒有線上日誌,所以重建控制檔案需要將RESETLOGS改成RESETLOGS才可以建立成功,否則會報以下錯誤:

ORA-01565: error in identifying file 'D:ORACLE8IORADATAORA8IREDO01.LOG'

ORA-27041: unable to open file

此時SCN號資訊如下:

sys@ORCL> select CHECKPOINT_CHANGE#,CONTROLFILE_CHANGE# from v$database;

CHECKPOINT_CHANGE#  CONTROLFILE_CHANGE#

 ------------------             -------------------

  0                          0

此時由於沒有歸檔日誌和線上日誌,無法做recovery。所以也就無法做alter database open Resetlogs了。此時可以加上_allow_resetlogs_corruption隱含引數,然後就可以alter database open resetlogs將資料庫開啟了。

當然如果v$datafile_headercheckpoint_change#是不相同的,那麼此時就沒有什麼常歸有效的辦法能將資料庫開啟了。如果相差不多,加上隱含引數_allow_resetlogs_corruption,然後alter database open resetlogs還是有可能可以開啟的。這個引數oracle是不建議加的,且加上這個引數也只是有可能可以開啟。這個引數是以最oldestSCN將資料庫開啟,所以最好system資料檔案的SCN號是最oldest的,否則容易產生大量的600號錯誤。

四、測試用例

1、檢視正常關閉/啟動過程

資料庫正常關閉,在資料庫啟動過程中:當System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN號都相同時,資料庫可以正常啟動

sys@ORCL> shutdown normal

Database closed.

Database dismounted.

ORACLE instance shut down.

sys@ORCL> startup mount

ORACLE instance started.

 

Total System Global Area  263049216 bytes

Fixed Size              2212448 bytes

Variable Size               234884512 bytes

Database Buffers         20971520 bytes

Redo Buffers                4980736 bytes

Database mounted.

sys@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

21677208

sys@ORCL> select checkpoint_change# from v$datafile;

CHECKPOINT_CHANGE#

------------------

        21677208

        21677208

        21677208

        21677208

        21677208

        21677208

6 rows selected.

SYS@ORCL> select checkpoint_change#,last_change# from v$datafile;

CHECKPOINT_CHANGE# LAST_CHANGE#

------------------ ------------

        21677208     21677208

        21677208     21677208

        21677208     21677208

        21677208     21677208

        21677208     21677208

        21677208     21677208

6 rows selected.

SYS@ORCL> select checkpoint_change# from v$datafile_header;

CHECKPOINT_CHANGE#

------------------

        21677208

        21677208

        21677208

        21677208

        21677208

        21677208

6 rows selected.

SYS@ORCL> alter database open;

Database altered.

看此時database的日誌檔案

Tue Mar 20 17:07:10 2012

ALTER DATABASE   MOUNT

Successful mount of redo thread 1, with mount id 1306217406

Allocated 3981120 bytes in shared pool for flashback generation buffer

Starting background process RVWR

Tue Mar 20 17:07:14 2012

RVWR started with pid=20, OS id=23412

Database mounted in Exclusive Mode

Lost write protection disabled

Completed: ALTER DATABASE   MOUNT

Tue Mar 20 17:11:27 2012

alter database open

Tue Mar 20 17:11:27 2012

LGWR: STARTING ARCH PROCESSES

Tue Mar 20 17:11:28 2012

ARC0 started with pid=21, OS id=23559

ARC0: Archival started

LGWR: STARTING ARCH PROCESSES COMPLETE

ARC0: STARTING ARCH PROCESSES

Tue Mar 20 17:11:29 2012

ARC1 started with pid=22, OS id=23561

Thread 1 opened at log sequence 1

  Current log# 1 seq# 1 mem# 0: /opt/oracle/oradata/orcl/redo01.log

Successful open of redo thread 1

MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set

Tue Mar 20 17:11:29 2012

SMON: enabling cache recovery

Tue Mar 20 17:11:29 2012

ARC2 started with pid=23, OS id=23563

ARC1: Archival started

ARC2: Archival started

ARC1: Becoming the 'no FAL' ARCH

ARC1: Becoming the 'no SRL' ARCH

Tue Mar 20 17:11:29 2012

ARC3 started with pid=24, OS id=23565

ARC2: Becoming the heartbeat ARCH

Successfully onlined Undo Tablespace 2.

Verifying file header compatibility for 11g tablespace encryption..

Verifying 11g file header compatibility for tablespace encryption completed

SMON: enabling tx recovery

Database Characterset is ZHS16GBK

No Resource Manager plan active

replication_dependency_tracking turned off (no async multimaster replication found)

ARC3: Archival started

ARC0: STARTING ARCH PROCESSES COMPLETE

Starting background process QMNC

Tue Mar 20 17:11:32 2012

QMNC started with pid=25, OS id=23567

Completed: alter database open

可以看到資料庫正常啟動沒有做任何instance recovery,和media recovery

2END SCNNULL

如果在啟動的過程中,End SCN號為NULL,則需要做instance recovery. 這種情況一般是資料庫不正常關閉導致  測試如下:

SYS@ORCL> shutdown abort

ORACLE instance shut down.

SYS@ORCL> startup mount

­ORACLE instance started.

Total System Global Area  263049216 bytes

Fixed Size              2212448 bytes

Variable Size               234884512 bytes

Database Buffers         20971520 bytes

Redo Buffers                4980736 bytes

Database mounted.

SYS@ORCL> select checkpoint_change# from v$datafile_header;

CHECKPOINT_CHANGE#

------------------

        21677211

        21677211

        21677211

        21677211

        21677211

        21677211

6 rows selected.

SYS@ORCL> select checkpoint_change#,last_change# from v$datafile;

CHECKPOINT_CHANGE# LAST_CHANGE#

------------------ ------------

        21677211

        21677211

        21677211

        21677211

        21677211

        21677211        ----可以看到last_change# 下面的內容為NULL

6 rows selected.

SYS@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

      21677211

SYS@ORCL> alter database open;  -------在這個過程中做了例項恢復

Database altered.

此時日誌檔案中記錄如下:

Tue Mar 20 17:15:03 2012

Shutting down instance (abort)

License high water mark = 3

USER (ospid: 23413): terminating the instance

Instance terminated by USER, pid = 23413

Tue Mar 20 17:15:04 2012

Instance shutdown complete

Tue Mar 20 17:15:32 2012

Starting ORACLE instance (normal)

LICENSE_MAX_SESSION = 0

LICENSE_SESSIONS_WARNING = 0

Picked latch-free SCN scheme 3

Using LOG_ARCHIVE_DEST_1 parameter default value as USE_DB_RECOVERY_FILE_DEST

Autotune of undo retention is turned on.

IMODE=BR

ILAT =27

LICENSE_MAX_USERS = 0

SYS auditing is disabled

Starting up:

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options.

Using parameter settings in server-side spfile /opt/oracle/product/db_1/dbs/spfileorcl.ora

System parameters with non-default values:

  processes                = 150

  sga_max_size             = 252M

  sga_target               = 152M

  control_files            = "/opt/oracle/oradata/orcl/control01.ctl"

  control_files            = "/opt/oracle/flash_recovery_area/orcl/control02.ctl"

  db_block_size            = 8192

  compatible               = "11.2.0.0.0"

  db_recovery_file_dest    = "/opt/oracle/flash_recovery_area"

  db_recovery_file_dest_size= 3882M

  db_flashback_retention_target= 30

  undo_tablespace          = "UNDOTBS1"

  remote_login_passwordfile= "EXCLUSIVE"

  db_domain                = ""

  dispatchers              = "(PROTOCOL=TCP) (SERVICE=orclXDB)"

  job_queue_processes      = 1000

  audit_file_dest          = "/opt/oracle/admin/orcl/adump"

  audit_trail              = "DB_EXTENDED"

  db_name                  = "orcl"

  open_cursors             = 300

  pga_aggregate_target     = 96M

  diagnostic_dest          = "/opt/oracle"

Tue Mar 20 17:15:33 2012

PMON started with pid=2, OS id=23761

Tue Mar 20 17:15:33 2012

VKTM started with pid=3, OS id=23763 at elevated priority

VKTM running at (10)millisec precision with DBRM quantum (100)ms

Tue Mar 20 17:15:33 2012

GEN0 started with pid=4, OS id=23767

Tue Mar 20 17:15:33 2012

DIAG started with pid=5, OS id=23769

Tue Mar 20 17:15:33 2012

DBRM started with pid=6, OS id=23771

Tue Mar 20 17:15:33 2012

PSP0 started with pid=7, OS id=23773

Tue Mar 20 17:15:33 2012

DIA0 started with pid=8, OS id=23775

Tue Mar 20 17:15:33 2012

MMAN started with pid=9, OS id=23777

Tue Mar 20 17:15:33 2012

DBW0 started with pid=10, OS id=23779

Tue Mar 20 17:15:33 2012

LGWR started with pid=11, OS id=23781

Tue Mar 20 17:15:33 2012

CKPT started with pid=12, OS id=23783

Tue Mar 20 17:15:33 2012

SMON started with pid=13, OS id=23785

Tue Mar 20 17:15:33 2012

RECO started with pid=14, OS id=23787

Tue Mar 20 17:15:33 2012

MMON started with pid=15, OS id=23789

Tue Mar 20 17:15:33 2012

MMNL started with pid=16, OS id=23791

starting up 1 dispatcher(s) for network address '(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP))'...

starting up 1 shared server(s) ...

ORACLE_BASE from environment = /opt/oracle

Tue Mar 20 17:15:33 2012

ALTER DATABASE   MOUNT

Successful mount of redo thread 1, with mount id 1306255541

Allocated 3981120 bytes in shared pool for flashback generation buffer

Starting background process RVWR

Tue Mar 20 17:15:37 2012

RVWR started with pid=20, OS id=23802

Database mounted in Exclusive Mode

Lost write protection disabled

Completed: ALTER DATABASE   MOUNT

Tue Mar 20 17:24:26 2012

alter database open

Beginning crash recovery of 1 threads

Started redo scan

Completed redo scan

 read 68 KB redo, 47 data blocks need recovery

Started redo application at

 Thread 1: logseq 1, block 6600

Recovery of Online Redo Log: Thread 1 Group 1 Seq 1 Reading mem 0  --當前日誌檔案做例項恢復instance recovery

  Mem# 0: /opt/oracle/oradata/orcl/redo01.log

Completed redo application of 0.04MB

Completed crash recovery at

 Thread 1: logseq 1, block 6737, scn 21697600

 47 data blocks read, 47 data blocks written, 68 redo k-bytes read

Tue Mar 20 17:24:27 2012

LGWR: STARTING ARCH PROCESSES

Tue Mar 20 17:24:27 2012

ARC0 started with pid=21, OS id=24121

ARC0: Archival started

LGWR: STARTING ARCH PROCESSES COMPLETE

ARC0: STARTING ARCH PROCESSES

Tue Mar 20 17:24:28 2012

ARC1 started with pid=22, OS id=24123

Tue Mar 20 17:24:28 2012

ARC2 started with pid=23, OS id=24125

Thread 1 advanced to log sequence 2 (thread open)

ARC1: Archival started

ARC2: Archival started

ARC1: Becoming the 'no FAL' ARCH

ARC1: Becoming the 'no SRL' ARCH

ARC2: Becoming the heartbeat ARCH

Tue Mar 20 17:24:28 2012

ARC3 started with pid=24, OS id=24127

Thread 1 opened at log sequence 2

  Current log# 2 seq# 2 mem# 0: /opt/oracle/oradata/orcl/redo02.log

Successful open of redo thread 1

MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set

Successfully onlined Undo Tablespace 2.

Verifying file header compatibility for 11g tablespace encryption..

Verifying 11g file header compatibility for tablespace encryption completed

Tue Mar 20 17:24:28 2012

SMON: enabling cache recovery

SMON: enabling tx recovery

Database Characterset is ZHS16GBK

No Resource Manager plan active

replication_dependency_tracking turned off (no async multimaster replication found)

Starting background process QMNC

Tue Mar 20 17:24:29 2012

QMNC started with pid=25, OS id=24129

Completed: alter database open.

3SCN不同時恢復

oracle在啟動過程中三者當中有一個不同時,則需要做media recovery,步驟是:首先檢查是否需要media recovery,然後再檢查是否需要instance recovery.測試如下;

SYS@ORCL> alter tablespace tools begin backup;

Tablespace altered.

此時複製tools01.dbf 到別處

SYS@ORCL> create table tools (id number) tablespace tools;

Table created.

SYS@ORCL> alter tablespace tools end backup;

Tablespace altered.

SYS@ORCL> create table tools (id number) tablespace tools;

Table created.

SYS@ORCL> insert into tools values(10);

1 row created.

SYS@ORCL> commit;

Commit complete.

SYS@ORCL> shutdown abort;

ORACLE instance shut down.

複製 tools01.dbf 回來

SYS@ORCL> startup mount;

ORACLE instance started.

Total System Global Area  101785252 bytes

Fixed Size                   454308 bytes

Variable Size              75497472 bytes

Database Buffers           25165824 bytes

Redo Buffers                 667648 bytes

Database mounted.

SYS@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

     251084

SYS@ORCL> select checkpoint_change#,last_change# from v$datafile;

CHECKPOINT_CHANGE# LAST_CHANGE#

------------------ ------------

            251084

            251084

            251084

            251084

            251084

SYS@ORCL> select checkpoint_change# from v$datafile_header;

CHECKPOINT_CHANGE#

------------------

            251084

            251084

            251084

           250867

            251084

可以看到 資料檔案頭的SCN250867,小於資料檔案SCN 251084,和系統檢查好SCN 251084

SYS@ORCL> alter database open;    --提示做介質恢復

alter database open

*

ERROR at line 1:

ORA-01113: file 4 needs media recovery

ORA-01110: data file 4: 'D:\ORACLE\ORADATA\PUBTEST\TOOLS01.DBF'

SYS@ORCL> recover datafile 4;

Media recovery complete.

SYS@ORCL> alter database open;

Database altered.

此時日誌檔案中內容如下:

ALTER DATABASE RECOVER  datafile 4

Media Recovery Datafile: 4

Media Recovery Start

Starting datafile 4 recovery in thread 1 sequence 16

Datafile 4: 'D:\ORACLE\ORADATA\PUBTEST\TOOLS01.DBF'

Media Recovery Log

Recovery of Online Redo Log: Thread 1 Group 1 Seq 16 Reading mem 0

Mem# 0 errs 0: D:\ORACLE\ORADATA\PUBTEST\REDO01.LOG

Recovery of Online Redo Log: Thread 1 Group 2 Seq 17 Reading mem 0

Mem# 0 errs 0: D:\ORACLE\ORADATA\PUBTEST\REDO02.LOG

Media Recovery Complete

Completed: ALTER DATABASE RECOVER  datafile 4

Tue Mar 18 09:48:50 2008

alter database open

Tue Mar 18 09:48:50 2008

 Beginning crash recovery of 1 threads

Tue Mar 18 09:48:50 2008

Started first pass scan

Tue Mar 18 09:48:52 2008

Completed first pass scan

 83 redo blocks read, 50 data blocks need recovery

Tue Mar 18 09:48:52 2008

Started recovery at

Thread 1: logseq 17, block 29, SCN 0.0

Recovery of Online Redo Log: Thread 1 Group 2 Seq 17 Reading mem 0

  Mem# 0 errs 0: D:\ORACLE\ORADATA\PUBTEST\REDO02.LOG

Tue Mar 18 09:48:52 2008

Completed redo application

Tue Mar 18 09:48:52 2008

Ended recovery at

Thread 1: logseq 17, block 112, SCN 0.271189

 50 data blocks read, 50 data blocks written, 83 redo blocks read

Crash recovery completed successfully

Tue Mar 18 09:48:53 2008

LGWR: Primary database is in CLUSTER CONSISTENT mode

Thread 1 advanced to log sequence 18

Thread 1 opened at log sequence 18

  Current log# 3 seq# 18 mem# 0: D:\ORACLE\ORADATA\PUBTEST\REDO03.LOG

Successful open of redo thread 1.

Tue Mar 18 09:48:54 2008

SMON: enabling cache recovery

Tue Mar 18 09:48:54 2008

ARC0: Evaluating archive   log 2 thread 1 sequence 17

ARC0: Beginning to archive log 2 thread 1 sequence 17

Creating archive destination LOG_ARCHIVE_DEST_1: 'D:\ORACLE\ORA92\RDBMS\ARC00017.001'

ARC0: Completed archiving  log 2 thread 1 sequence 17

Tue Mar 18 09:48:54 2008

Undo Segment 1 Onlined

Undo Segment 2 Onlined

Undo Segment 3 Onlined

Undo Segment 4 Onlined

Undo Segment 5 Onlined

Undo Segment 6 Onlined

Undo Segment 7 Onlined

Undo Segment 8 Onlined

Undo Segment 9 Onlined

Undo Segment 10 Onlined

Successfully onlined Undo Tablespace 1.

Tue Mar 18 09:48:54 2008

SMON: enabling tx recovery

Tue Mar 18 09:48:54 2008

Database Characterset is ZHS16GBK

replication_dependency_tracking turned off (no async multimaster replication found)

Completed: alter database open

五、深入分析checkpoint_change#

1、系統檢查點(記錄在控制檔案中)

SYS@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

        21728618

2、資料檔案檢查點(記錄在控制檔案中)

SYS@ORCL> select file#,checkpoint_change#,last_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE# LAST_CHANGE#

---------- ------------------ ------------

       1        21728618

       2        21728618

       3        21728618

       4        21728618

       5        21728618

       6        21728618

6 rows selected.

3、資料檔案頭檢查點(記錄在資料檔案中)

SYS@ORCL> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#

---------- ------------------

       1        21728618

       2        21728618

       3        21728618

       4        21728618

       5        21728618

       6        21728618

6 rows selected.

以上三個checkpoint_change#要一致(只讀、離線表空間除外),資料庫才能正常開啟。否則會需要進行一步的處理。正常關庫時,會生成新的檢查點,寫入上述三個checkpoint_change#,同時資料檔案中的last_change#也會記錄下該檢查點,也就是說三個checkpoint_change#last_change#記錄著同一個值。透過以下SQL可以證明:

SYS@ORCL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SYS@ORCL> startup mount

ORACLE instance started.

Total System Global Area  263049216 bytes

Fixed Size              2212448 bytes

Variable Size               230690208 bytes

Database Buffers         25165824 bytes

Redo Buffers                4980736 bytes

Database mounted.

SYS@ORCL> select file#,checkpoint_change#,last_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE# LAST_CHANGE#

---------- ------------------ ------------

       1        21732562    21732562

       2        21732562    21732562

       3        21732562    21732562

       4        21732562    21732562

       5        21732562    21732562

       6        21732562    21732562

6 rows selected.

SYS@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

        21732562

SYS@ORCL> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#

---------- ------------------

       1        21732562

       2        21732562

       3        21732562

       4        21732562

       5        21732562

       6        21732562

6 rows selected.

資料庫成功開啟後,資料檔案中的last_change#會被清空。正常關庫時,再重新下最後的檢查點。shutdown abort關庫,這個值是空的(感興趣可自行驗證),此時資料庫需要進行例項恢復(不需要使用者干預),恢復後資料庫才正常開啟。checkpoint_change#last_change#實際上全部來自於SCN,可以透過下面的語句驗證:

sys@ORCL> alter database open;

Database altered.

SYS@ORCL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

------------------------

             21732835

使用查詢系統SCN號的函式,可以發現checkpoint_change#與之是接近的。SCN有很多觸發的條件,可能不會特別接近。下面舉幾個全備後恢復的例子,以及相關場景下checkpoint_change#的情況。

問題1:資料檔案損壞的恢復

此時控制檔案中記錄的checkpoint_change#比資料檔案頭中記錄的要大,資料庫需要介質或者例項恢復。

SYS@ORCL> startup

Database mounted.

ORA-01113: file 1 needs media recovery

ORA-01110: data file 1: '/u02/oradata/orcl/system01.dbf'

恢復一下,資料庫就可以開啟了。

SYS@ORCL> recover database;

ORA-00279: change 539624 generated at 10/18/2011 08:27:31 needed for thread 1

ORA-00289: suggestion : /u02/oradata/orcl/arc/1_5_764840495.dbf

ORA-00280: change 539624 for thread 1 is in sequence #5

 

 

Specify log: {=suggested | filename | AUTO | CANCEL}

auto

ORA-00279: change 540768 generated at 10/18/2011 12:17:11 needed for thread 1

ORA-00289: suggestion : /u02/oradata/orcl/arc/1_6_764840495.dbf

ORA-00280: change 540768 for thread 1 is in sequence #6

ORA-00278: log file '/u02/oradata/orcl/arc/1_5_764840495.dbf' no longer needed for this recovery

Log applied.

Media recovery complete.

SYS@ORCL> alter database open;

Database altered.

問題2:控制檔案損壞的恢復

如果控制檔案損壞,使用備份的控制檔案是無法直接開啟資料庫的。

SYS@ORCL> startup

Database mounted.

ORA-01122: database file 1 failed verification check

ORA-01110: data file 1: '/u02/oradata/orcl/system01.dbf'

ORA-01207: file is more recent than controlfile - old controlfile

會提示資料檔案與控制檔案新,實際上就是控制檔案中記錄的checkpoint_change#比資料檔案頭中的checkpoint_change#要小,這種情況是不能開啟資料庫的。但資料可以啟動到mount狀態,此時可以用命令:

SYS@ORCL> alter database backup controlfile to trace;

生成一個控制檔案的指令碼,在udump目錄中。使用該指令碼可以重建控制檔案,進行例項恢復後或開啟資料庫。如果沒有備份的控制檔案,資料庫只能開啟的nomount狀態,不能獲取重建控制檔案的指令碼。如果資料庫不太複雜,可以手寫一個。

問題3:資料檔案、控制檔案全部損壞

當然都有備份,日誌是好的。恢復資料檔案、控制檔案後,資料庫仍然是無法開啟的。

SYS@ORCL> startup

Database mounted.

ORA-00314: log 1 of thread 1, expected sequence#  doesn't match

ORA-00312: online log 1 thread 1: '/u02/oradata/orcl/redo01.log'

提示的意思也就是日誌中的檢查點比較控制檔案中記錄的大。

SYS@ORCL> select checkpoint_change# from v$datafile;

CHECKPOINT_CHANGE#

------------------

            539624

            539624

            539624

            539624

            539624

SYS@ORCL> select checkpoint_change# from v$datafile_header;

CHECKPOINT_CHANGE#

------------------

            539624

            539624

            539624

            539624

            539624

SYS@ORCL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

            539624

SYS@ORCL> select * from v$log;

GROUP#  THREAD#  SEQUENCE#  BYTES  MEMBERS  ARC  STATUS FIRST_CHANGE#  FIRST_TIM

 ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------

1          1          5   10485760          1 NO  CURRENT                 539571 18-OCT-11

2          1          4   10485760          1 YES INACTIVE                539116 18-OCT-11

3          1          3   10485760          1 YES INACTIVE                537456 18-OCT-11

此時可以使用下面的命令恢復資料庫:

SYS@ORCL> recover database using backup controlfile;

恢復成功後,v$database中記錄的checkpoint_change#並未發生變化。

SYS@ORCL> select checkpoint_change# from v$datafile;

CHECKPOINT_CHANGE#

------------------

            602574

            602574

            602574

            602574

            602574

SYS@ORCL> select checkpoint_change# from v$datafile_header;

CHECKPOINT_CHANGE#

------------------

            602574

            602574

            602574

            602574

            602574

SYS@ORCL>  select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

            539624

因為不一致,所以資料庫仍然打不開:

SYS@ORCL> alter database open;

alter database open

*

ERROR at line 1:

ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

SYS@ORCL> alter database open resetlogs;

alter database open resetlogs

*

ERROR at line 1:

ORA-01113: file 1 needs media recovery

ORA-01110: data file 1: '/u02/oradata/orcl/system01.dbf'

此時的情況類似於問題2,解決辦法也相同。shutdown abort,startup nomount,重建控制檔案,recover database,alter database open;

問題4、冷備過後新建的資料檔案損壞,且無備份

這種情況的處理辦法:

SYS@ORCL> restore’備份的資料檔案’;

SYS@ORCL> startup;

會提示無法定位資料檔案,資料庫無法開啟,alter database create datafile提示無法定位的資料檔名稱;此時檢視checkpoint_change#,會發現新建的與其它的不相同。

SYS@ORCL> set autorecovery on

SYS@ORCL> recover database;

SYS@ORCL> alter database open;

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

相關文章