SCN headroom问题解决方案
轉載請注明出處,謝謝!
?---好久沒來逛ITPUB了,發一篇大家關心的問題
1.?? SCN headroom簡介
SCN是Oracle內部使用的邏輯時鐘,用于區分事務操作的先后次序以及確保事務操作的一致性。它由48位的一串單向序列數字來實現的,因此最大值不能超過2的48次方,為了確保這個48位的SCN能夠用足夠長的時間(500年),Oracle對SCN序列做出了一個限制,即每秒鐘SCN最大增長不能超過16K。為了平衡業務的高峰和低谷,Oracle使用了一個十分簡單的算法來貫徹上述限制,就是以從1988年1月1日0點0分0秒為基準時間,至當前時間的秒鐘數乘以16K,就是當前SCN的最大允許值,我們稱為SCN Headroom。從SCN Headroom 的算法可知,Headroom值是隨時間動態變化的,按照oracle公司說法,如果在某個時刻SCN達到了這個最大值,那么事務就無法提交,需要等到下一秒,當Headroom值又變大了,才能繼續進行事務的提交;但在實際運行時,如果數據庫當前的SCN已經達到了Headroom的最大值時,該機制有很大可能會造成數據庫保護性宕機。
當然,在正常情況下,每秒16K的SCN增量完全可以滿足應用的正常使用,但是在實際使用中,已經證實一些特定的應用模式會觸發Oracle的內部Bug,根據經驗這些應用基本都是跑報表類型的業務、采用高并發、select... for update 、執行效率非常差的sql和相同對象的DDL語句同時執行、大量數據處理一次性提交(大事物)等等。最終導致SCN在短時間內的大幅增長,久而久之,SCN很快就會逼近Headroom的上限。
除了Oracle Bug引發SCN大幅增長以外,Oracle數據庫固有的DBLINK運作機制也在其中起了推波助瀾的作用。
Oracle數據庫為了實現分布式處理,在多個數據庫之間做DBLINK訪問的時候,會將兩個數據庫的SCN進行同步,也就是將較高的SCN同步至參與DBLINK的另外一個庫,使兩個庫的SCN序列一致。這個機制就可能把SCN增長異常傳播到其它的數據庫服務器上,并且隨著不同數據庫的業務高峰和低谷相互傳染,大大加速了SCN的增長,并最終造成嚴重的后果。
2.?? SCN跳變源的尋找方式
2.1.????? 尋找跳變源的有效方法
?? 為了找到跳變源,如果現網的dblink使用非常復雜并且headroom下降的問題涉及了幾十套甚至是上百套數據庫,這個時候查找跳變源會變得復雜。對于打了2012年1月以后的psu補丁的數據庫系統可以通過alert判斷,對于沒有打2012年1月以后的補丁就需要我們做好監控。所以一般這種情況下我們會對現網的所有的數據庫進行監控,這樣做的好處是我們可以第一時間知道當前所有系統的scn headroom的現狀,并且如果出現headroom驟降我們可以第一時間進行相應查找跳變源,而不需要等到數據庫后臺報錯了才知道headroom問題,如果后臺已經報錯說明headroom問題已經非常嚴重。
1) 對于已經打了2012 年1 月以后PSU 補丁的數據庫系統,當SCN 傳播發生時,
ALERT LOG 中會有記錄,可以通過ALERT LOG 查找問題的系統:
Advanced SCN by 13238271 minutes worth to 0x0bd6.00000f21, by distributed transaction remote logon, remote DB: ORA10G. Client info : DB logon user SCOTT, machine gc, program sqlplus@gc (TNS V1-V3), and OS user oracle
2) 而對于未安裝上述補丁的數據庫,則可以通過在數據庫上運行3.1步驟中提供的腳本,列出SCN歷史的剩余天數,依照SCN 序列突變的先后時間來找出源頭,或是縮小范圍便于進一步查證。但是如果現網數據庫數量非常多的話一套一套查是非常不現實的,所以一般情況下我們都會做SCN的監控。
2.2.????? SCN headroom的實時情況監控
分鐘級監控(時間可以自行調整):監控主機上的部署crontab sh /u01/oracle/ljl/scn_monitor.sh? 調用存過scn_monitor生成監控表scn_mon(最好建成分區表提升查詢效率)。
監控腳本內容略:
NOTE:腳本內容可以根據需求自己控制,如果擔心監控庫會加重庫與庫之間的scn同步并且影響我們對跳變源的判斷,可以使用shell或者python直接調用,從而避免監控庫使用dblink。近期在電力使用的python腳本監控方式待驗證成功后續再增加。
3.?? SCN跳變源分析
3.1.????? SCN headroom歷史紀錄分析
查看近期的headroom歷史記錄(按分統計)時間范圍不要選的太大,因為我們選擇的是小時為單位所以時間跨度大了以后曲線會反映不出跳變點,定位SCN headroom下降的大概時間點和當前SCN headroom總體趨勢,查詢語句如下:
?select *
? from monitor.scn_mon a
?where a.date_time >= '2016/10/23'
?? order by a.date_time
定位SCN headroom下降的大概時間點和當前SCN headroom總體趨勢:
先把我所有系統的大體scn headroom的趨勢對比不同時間點的headroom剩余時間,如果呈現下降趨勢的,取其中一套headroom在下降的數據庫,進行plsql作圖找到大致的下降時間點和整體的下降趨勢
?select *
? from monitor.scn_mon a
?where a.date_time >= '2016/10/23'
?? and a.host_name = ''
?? order by a.date_time
????????????????????????? 圖1-1
如果曲線如圖1-1,有明顯的垂直下降的情況,很可能是被其他數據庫通過dblink傳染的,這個時候就要定位這個斷崖的時間點,然后執行如下語句找到當前時間或者前一分鐘的headroom剩余時間最小的那臺主機(也就是最先跳變的數據庫),如果確定了有一套庫在每次的垂直下降的時間點headroom都最先下降那么他往往就是源頭庫或者最先感染的庫。
?select *
? from monitor.scn_mon a
?where a.date_time >= '2016/10/23 21:00:00'
?and a.date_time <= '2016/10/23 21:02:00'
?? order by a.date_time
如果曲線如圖1-2,雖然headroom是一直在下降的但是下降的幅度很緩慢甚至有些時間點還是往上漲的,那么headroom下降的原因往往是它本身進程異常調用而引起的問題,這個時候基本可以判定他的scnheadroom下降問題不是其他系統通過dblink同步而導致的。
???????????????????????????????? 圖1-2
?
3.2.????? 數據庫SCN自增長情況分析
數據庫SCN自增長查看(即call scn kcmgas的平均每秒調用值),SCN自增長平均每秒超過16000需要重點分析(按照SCN headroom 的計算方式,平均每秒超過16000,會引起全網SCN headroom下降),可以通過下面語句查看SCN自增長:
9i數據庫(需開啟STATSPACK)
?
10g以上數據庫
單實例查詢:
? ?select to_char(b.end_interval_time,'YYYY-MM-DD HH24:MI:SS') as time,
??????? c.snap_id,
??????? trunc((lead(c.value, 1, c.value) over(order by c.snap_id) - c.value) / (select to_number(substr(replace(a.snap_interval, '+00000 ', ''), 1, 2), 99) * 3600 +
?????? to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99) * 60 +
?????? to_number(substr(replace(a.snap_interval, '+00000 ', ''), 7, 2), 99)
? from dba_hist_wr_control a)) as per_s_value
????????? from dba_hist_sysstat c,dba_hist_snapshot b
???????? where
?????????????? b.snap_id=c.snap_id
?????????? and b.instance_number=c.instance_number
?????????? and c.instance_number = 1 ----或者2
?????????? and c.stat_name = 'calls to kcmgas'
???????? order by 1 desc;
多實例查詢:
select c.instance_number,
?????? to_char(b.end_interval_time, 'YYYY-MM-DD HH24:MI:SS') as time,
?????? c.snap_id,
?? ????trunc((lead(c.value, 1, c.value)
????????????? over(partition by c.instance_number order by c.snap_id) -
????????????? c.value) /
???????????? (select to_number(substr(replace(a.snap_interval, '+00000 ', ''),
????????????????????????????????????? 1,
????????????????????????????????????? 2),
?????????????????????????????? 99) * 3600 +
???????????????????? to_number(substr(replace(a.snap_interval, '+00000 ', ''),
????????????????????????????????????? 4,
????????????????????????????????????? 2),
?????????????????????????????? 99) * 60 +
???????????????????? to_number(substr(replace(a.snap_interval, '+00000 ', ''),
????????????????????????????????????? 7,
????????????????????????????????????? 2),
?????????????????????????????? 99)
??????????????? from dba_hist_wr_control a)) as per_s_value
? from dba_hist_sysstat c, dba_hist_snapshot b
?where b.snap_id = c.snap_id
?? and b.instance_number = c.instance_number
?? and c.stat_name = 'calls to kcmgas'
?order by 1, 2 desc;
3.3.????? Session SCN調用情況分析
如果前兩步都無法定位,則需要關注持續活動非常久的session,并且關注session的SCN調用情況:
---建議通過value desc,last_call_et desc 排序來看,一般情況下value過千萬,甚至上億,LAST_CALL_ET超過幾個小時那么該會話可能就是引起跳變的可疑的會話。
3.4.????? 確認感染源
?分析到了源頭庫或者是最先感染的庫,通過取下降高峰時段的AWR進行最終確認。
select b.end_interval_time,
?
??????? c.snap_id,
?
??????? trunc((lead(c.value, 1, c.value) over(order by c.snap_id) - c.value) / (select to_number(substr(replace(a.snap_interval, '+00000 ', ''), 1, 2), 99) * 3600 +
?
?????? to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99) * 60 +
?
?????? to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99)
?
? from dba_hist_wr_control a))
?
????????? from dba_hist_sysstat c,dba_hist_snapshot b
?
??????? ?where
?
?????????????? b.snap_id=c.snap_id
?
?????????? and b.instance_number=c.instance_number
?
?????????? and c.instance_number = 1 ----或者2
?
?????????? and c.stat_name = 'calls to kcmgas'
?
???????? order by 1 desc;
3.5.????? 異常session定位
?
如果已經分析到源頭庫,緊接著來定位session,可以直接登錄該庫進行檢查定位:
?
腳本略
當前面的2、3、4基本初步能找出跳變源,確定了可能的跳變源數據庫后,可以通過本語句進行確認相關異常會話,使用VALUE,PREVALUE,LAST_CALL_ET,event,SQL_TEXT結合起來綜合判斷。
如:value過千萬,甚至上億,LAST_CALL_ET超過幾個小時,event是異常等待,且SQL_TEXT進行了append insert操作或者語句中有parallel參數那么該會話就是引起跳變的最可疑的會話。
處理可疑會話跟業務側確認該會話的用途是否可以停止或者后臺數據庫層直接kill,并且對這些會話進行優化接下來繼續觀察headroom是否回漲,如果并沒有發現可疑會話那就繼續重點監控該數據庫觀察時候有可以會話或者后臺進程異常調用scn,必要時可以嘗試申請在scn headroom下降的大概時間點窗口申請嘗試停數據庫,然后對比headroom曲線是否有變化,如果headroom回漲,那么可以基本定位是該數據庫,如果以上步驟對headroom沒有任何影響,則該可以跳變源可能就不是真正的跳變源請從第一步開始分析另一個可疑的跳變源。
?
?
?
?
?
4.?? SCN問題解決方案
?
1)數據庫被外部數據庫通過DBLINK傳染,造成SCN序列異常增長
如果數據庫被外部數據庫通過DBLINK傳染,而造成SCN序列異常增長,而應用改造減少DBLink有無法在短期實現,那么未防止進一步傳染其他健康的數據庫,請及時將它們進行dblink的隔離。
??? 2)數據庫本身觸發Bug,造成SCN序列的異常增長
如果數據庫本身觸發Bug,造成SCN序列的異常增長,即3.2步驟發現數據庫scn自身調用異常,則可以對該庫應用2012年一月份以后的補丁(該補丁也存在部分bu所以建議打到最新的補丁),并且設置:_external_scn_rejection_threshold_hours=24。這個設置降低可以SCN Headroom的頂部空間,11.2.0.2以前的版本缺省的設置容量至少為31天,降低為 24 小時,可以增大SCN允許增長的合理空間。如果該數據庫版本沒有對應的補丁,建議升級,如果升級需要跨多個版本為了降低風險可以進行業務改造防止傳染其他健康數據庫或者直接進行遷移。
因為沒有對應的補丁的版本數據庫往往是比較舊的,升級的可能會涉及跨多個版本,所以一般情況下我們不建議升級而是直接遷移更安全或者進行業務改造禁用dblink。
以下版本oracle是對應沒有補丁程序的:
·???????????? All versions up to and including 9.2.0.7
·???????????? Versions 10.1.0.2 to 10.1.0.4 inclusive
·???????????? Versions 10.2.0.1 and 10.2.0.2
·???????????? Version 11.1.0.6
·???????????? Version 11.2.0.1
備注:所有的解決方案都是存在風險的,所以請考慮周全在確定使用哪一種方式。
?
?
?
?
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/30068249/viewspace-2130002/,如需轉載,請注明出處,否則將追究法律責任。
轉載于:http://blog.itpub.net/30068249/viewspace-2130002/
總結
以上是生活随笔為你收集整理的SCN headroom问题解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt [GC9-13]:HUD-转向灯、
- 下一篇: 05.bean依赖注入的三种方式