【恩墨學院】深入剖析 - Oracle SCN機制詳細解讀

恩墨學院發表於2018-04-13

周玉其

SCN可以說是Oracle中一個很基礎的部分,但同時它也是一個很重要的。它是系統中維持資料的一致性和順序恢復的重要標誌,是資料庫非常重要的一種資料結構。


SCN介紹


SCN即系統改變號(System Change Number),是在某個時間點定義資料庫已提交版本的時間戳標記。 Oracle為每個已提交的事務分配一個唯一的SCN。 SCN的值是對資料庫進行更改的邏輯時間點。 Oracle使用此編號記錄對資料庫所做的更改。在資料庫中,SCN也可以說是無處不在,資料檔案頭,控制檔案,資料塊頭,日誌檔案等等都標記著SCN。也正是這樣,資料庫的一致性維護和SCN密切相關。不管是資料的備份,恢復都是離不開SCN的。


SCN是一個6位元組(48bit)的數字,其值為281,474,976,710,656(2^48),分為2個部分:


SCN_BASE是一個4位元組(32bit)的數字

SCN_WRAP是一個2位元組(16bit)的數字


每當SCN_BASE達到其最大值(2^32 = 4294967296)時,SCN_WRAP增加1,SCN_BASE將被重置為0,一直持續到SCN_WRAP達到其最大值,即2^16 = 65536。


SCN =(SCN_WRAP * 4294967296)+ SCN_BASE


SCN隨著每個事務的完成而增加。提交不會寫入資料檔案,也不更新控制檔案。當發生checkpoint時,控制檔案更新,SCN被寫入到控制檔案。


當前的SCN可以透過以下查詢獲得:

select dbms_flashback.get_system_change_number scn from dual;

select current_scn from v$database;


四種重要的SCN


在理解這幾種SCN之前,我們先看下oracle事務中的資料變化是如何寫入資料檔案的:


第一步:事務開始;

第二步:在buffer cache中找到需要的資料塊,如果沒找到,從資料檔案中載入buffer cache中;

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

第四步:事務提交,LGWR程式將log buffer中的“髒資料”的日誌條目寫入redo log file中;

第五步:當發生checkpoint,CKPT程式更新所有資料檔案的檔案頭中的資訊,DBWn程式則負責將Buffer Cache中的髒資料寫入到資料檔案中。


經過上述5個步驟,事務中的資料變化最終被寫入到資料檔案中。但是,一旦在上述中間環節資料庫意外當機了,在重新啟動時如何知道哪些資料已經寫入資料檔案、哪些沒有寫呢?(同樣,在DG、streams中也存在類似疑問:redolog中哪些是上一次同步已經複製過的資料、哪些沒有)


SCN機制就能比較完善的解決上述問題。 SCN是一個數字,確切的說是一個只會增加、不會減少的數字。正是它這種只會增加的特性確保了 Oracle知道哪些應該被恢復、哪些應該被複制。


總共有4種SCN


系統檢查點(System Checkpoint)SCN

資料檔案檢查點(Datafile Checkpoint)SCN

結束SCN(Stop SCN)

開始SCN(Start SCN)


(1)System Checkpoint SCN


當checkpoint完成後,ORACLE將System Checkpoint SCN號存放在控制檔案中。我們可以透過下面SQL語句查詢:

select checkpoint_change# from v$database;


(2)Datafile Checkpoint SCN


當checkpoint完成後,Oracle將Datafile Checkpoint SCN存放在控制檔案中。我們可以透過下面SQL語句查詢所有資料檔案的Datafile Checkpoinnt SCN。

select name,checkpoint_change# from v$datafile;


(3)Start SCN


Oracle將StartSCN存放在資料檔案頭中。這個SCN用於檢查資料庫啟動過程是否需要做media recovery。我們可以透過以下SQL語句查詢:

select name,checkpoint_change# from v$datafile_header;


(4)Stop SCN


ORACLE將StopSCN存放在控制檔案中。這個SCN號用於檢查資料庫啟動過程是否需要做instance recovery。我們可以透過以下SQL語句查詢:

select name,last_change# from v$datafile;


在資料庫正常執行的情況下,對可讀寫的online資料檔案,該SCN號為NULL。


SCN與資料庫啟動


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


SCN與資料庫關閉


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


Q&A

Q

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

如果有表空間read only,那麼該表空間的所有datafile的start SCN和stop SCN將被凍結,這個時候就跟System Checkpoint SCN不一致,但在庫open的時候是不需要做media recovery的,如果沒有DatafileCheckpoint SCN就無法判斷這些datafile是否是最新的。


可能遇到的SCN問題


首選我們看幾個跟SCN有關的概念:


Reasonable SCNLimit(RSL)


RSL = (當前時間 - 1988年1月1日)*24*3600*SCN每秒最大可能增長速率


也就是從1988年1月1日開始,假如SCN按最大速率增長,當天理論上的最大值。


最大增長速率:在11.2.0.2之前是16384,在11.2.0.2及之後版本是32768

在11.2.0.2版本之後由_max_reasonable_scn_rate引數控制

Oracle 實戰



該引數不建議修改。


SCN Headroom


Headroom(天) = (Reasonable SCN Limit -CurrentSCN)/ SCN每秒最大可能增長速率/3600/24


也就是如果SCN按最大速率增長,達到當前理論最大值需要的天數。這個值可以用來判斷SCN增長速率是否過快。


那麼,SCN Headroom如果獲取呢?


參考MOS: Bug 13498243 -"scnhealthcheck.sql" script (文件 ID 13498243.8),打上該BUG的patch之後,將在$ORACLE_HOME/rdbms/admin中增加scnhealthcheck.sql檔案,該檔案就是用來檢查SCN是否正常。


另外還有一篇MOS文件,專門對該指令碼的輸出做了解釋。即Installing, Executing and Interpreting output from the"scnhealthcheck.sql" script (文件 ID 1393363.1)。


執行該指令碼,結果如下:


Oracle 實戰


這個結果我們仍然無法得到該資料庫的具體SCN Headroom,下面這個SQL是從scnhealthcheck.sql中找到的,可以直接查到SCN Headroom的值(indicator欄位)。

Oracle 實戰


Q&A

Q

針對上面的查詢結果,是不是意味著過1647天之後,SCN就將達到最大值?

不會,因為1647天之後,Current SCN會變大,Reasonable SCN Limit同樣也會變大,正常情況下,SCNHeadroon只會變大不會變小。



SCN headroom過小的問題


如果SCN正常增長,達到最大值大約可以用500年,SCN headroom的值也會隨著時間的推移慢慢變大,但是可能由於BUG、用特殊手段人為調整、dblink傳播導致SCN增長出現異常。但如果出現SCN headroom過小,alert log會出現警告:Warning: The SCN headroom for this database is only NN days!


原因定位:


1. 透過下面這篇文件裡提供的指令碼,該指令碼類似於建立AWR,可以按snap_id對dba_hist_sysstat裡的某個stat_name做統計,我們這裡的Stat_name選擇calls to kcmgas。

How to Extract the Historical Values of aStatistic from the AWR Repository (文件 ID 948272.1)


2. 透過查詢V$ARCHIVED_LOG單位時間內scn變化


3. 透過上面兩個方式得出的結果分析,如果是非持續突發增長,認為很可能是透過dblink引起;


4. 同時比較awr報告中“callsto kcmgas”    和“user commits”,如果user commits也是高速增長,很可能是自身引起;


kcmgas是Oracle分配scn的函式,在一個空庫上做測試,可以看出每分配一次scn,calls to kcmgas的統計增加1,所以calls to kcmgas的量可以作為scn的增長量來分析。

Oracle 實戰



ORA-19706: Invalid SCN錯誤


[1376995.1]裡的介紹,在2012年1月CPU或PSU裡增加_external_scn_rejection_threshold_hours引數,11.2.0.2及以後的版本,預設為1天即24小時,其他版本預設為31天即744小時,相當於把拒絕外部SCN連線的閾值調大了,因而更加容易引發ORA-19706錯誤。該引數對資料庫自身產生的SCN遞增沒有影響。Bug 13554409 - Fix for bug13554409 [ID 13554409.8]的裡對該問題也有介紹。


ORA-19706錯誤:最常見的就是拒絕dblink連線的時候,如A庫跟B庫透過dblink連線,A的SCN有透過人為調整增大許多,連線B庫的時候,Oracle會判斷該SCN傳播過來之後,如果會導致SCN headroom小於_external_scn_rejection_threshold_hours設定的閾值,則拒絕連線


相關參考:SCN、ORA-19706錯誤和_external_scn_rejection_threshold_hours引數


如果打完2012年1月CPU或PSU後遇到ORA-19706錯誤,對於以下這些版本的資料庫:


Oracle 10.2.0.5

Oracle 11.1.0.7

Oracle 11.2.0.2

Oracle 11.2.0.3


oracle建議給資料庫安裝2012年4月釋出的PSU,並在安裝該PSU的基礎上,安裝補丁13916709。如果是叢集架構,同時給叢集軟體最新安裝PSU。引數_external_scn_rejection_threshold_hours在2012年4月(包含2012年4月)以後釋出的PSU/CPU中,11.2.0.2及以後的版本,是1天即24小時,其他版本是31天即744小時。其他版本:先升級到高版本,再按照上面的方法處理。


總結


如果發現SCN有異常,需要及時透過上述方法來打上最新的PSU,同時儘量少用DBLINK,從系統設計角度來講也是不推薦這種系統間強耦合的設計。



作者介紹

周玉其    雲和恩墨技術顧問

8年以上資料庫開發、運維經驗。思維敏捷,曾在電信、物流行業從事資料庫開發、運維工作,擅長PL/SQL開發、效能最佳化、故障診斷。


恩墨學院隸屬於雲和恩墨(北京)資訊科技有限公司,致力於提供專業高水準的與大資料培訓服務,挖掘培養大資料與資料庫人才。恩墨學院提供包括個人實戰技能培訓、個人認證培訓、企業內訓在內的全方位大資料和資料庫技術培訓。ACE級別超強師資,配備專業實驗室,沉浸式學習與訓練,專業實驗室、配備專業助教指導訓練。能迅速融入專家圈子,業內資源豐富,迅速積累職場人脈。課程包括:班、Oracle 、Oracle OCP考試等。


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

相關文章