解析實時的DB time過程分析

531968912發表於2016-05-18
在我們檢視awr報告的時候總是會有一個關鍵指標需要注意,那就是DB time,這個指標一般都是透過awr報告來看到的。
比如我們得到的awr報告頭部顯示的下面的資訊,我們就清楚的知道DB time是1502.06 mins,相對於Elapsed time來說,將近有20倍的壓力。這個問題肯定需要關注。
              Snap Id      Snap Time      Sessions Curs/Sess
            --------- ------------------- -------- ---------
Begin Snap:      6219 21-Jul-15 22:00:08       583       2.5
  End Snap:      6220 21-Jul-15 23:00:44       639       2.4
   Elapsed:               60.61 (mins)
   DB Time:            1,502.06 (mins)
當然我們也不大可能一下子生成幾十個awr報告,然後就為了得到這個DB time值。
在之前的部落格中也分享過如何來結合shell指令碼抓取資料庫的負載資訊。
http://blog.itpub.net/23718752/viewspace-1168027/
比如得到的結果如下:
DB_NAME   BEGIN_SNAP   END_SNAP SNAPDATE             LVL DURATION_MINS     DBTIME
--------- ---------- ---------- -------------------- --- ------------- ----------
XXX          93464      93465 21 Aug 2015 00:00      1            30         15
               93465      93466 21 Aug 2015 00:30      1            30          5
               93466      93467 21 Aug 2015 01:00      1            30          5
               93467      93468 21 Aug 2015 01:30      1            30         13
               93468      93469 21 Aug 2015 02:00      1            30         24
這個對於日常的使用其實也基本夠用,有一個最大的缺點就是這個指標其實是基於歷史快照的,比如現在是15:30分,每隔一個小時生成一次快照,那麼我想看看15:30這個時間點的大致資料庫負載情況就無法實現了。
這個工作其實還是有一定的使用意義的,比如我們想透過orabbix來做這種型別的監控,不能專門再等1個小時吧,或者把時間調短,但是想必會對效能還是有一定的影響,因為我們只是想知道DB time的情況,其它的資訊先放一放,暫時不需要。
Oracle在10g推出的時間模型,裡面有一個很重要的資料字典表是DBA_HIST_SYS_TIME_MODEL,但是裡面都是歷史的資訊,沒有最新的資訊,這個時候可以藉助另外一個動態效能檢視 v$sys_time_model
所以對於這個監控項,自己也是信心滿滿,寫了下面的語句,看似也能達到效果。
select 
round 
       (
    (select round(e.value / 1000000,2) dbtime 
                        FROM v$SYS_TIME_MODEL e 
                        WHERE 
                         e.STAT_NAME = 'DB time')*100/ 
      (select ((systimestamp+0)-startup_time)*24*60*60 dbtime_duartion_ 
                        from v$instance )  
   ,2)      dbtime_per                  
     from dual;
我的思路就是當前的DB time的值可以得到,但是需要找一個基準,這個時候又沒有其它可參考的基準,我就想到使用資料庫例項啟動的時間,初始化啟動的時候DB time的值會從0開始初始化,逐漸遞增。
當然還是有誤差的,比如資料庫從nomount,mount到open階段,db time的值就開始逐漸遞增了,可能參考的基準時間會有一些誤差,但是相對來說很小。
比如資料庫open狀態下
SQL> select value/1000000 ,t.*from v$sys_time_model t where stat_name='DB time'
VALUE/1000000    STAT_ID STAT_NAME   VALUE
------------- ---------- ---------- ----------
   130.364805 3649082374 DB time    130364805

然後停庫,啟動到mount階段。
VALUE/1000000    STAT_ID STAT_NAME    VALUE
------------- ---------- ----------- ----------
     6.057183 3649082374 DB time       6057183
啟動到Open階段
VALUE/1000000    STAT_ID STAT_NAME      VALUE
------------- ---------- ---------------------
    10.063956 3649082374 DB time      10063956
可以看到DB time都是在逐漸遞增的過程,大體情況下這種方式似乎還是一種不錯的選擇。
但是配置到orabbix監控中之後,仔細對比快照中的資料庫負載,發現資料庫的負載情況會有一些錯誤,有些庫中透過快照檢視負載在40%左右,但是透過實時取得的資料得到的結果負載時40%,這個時候我還是相信快照中的DB time.
自己帶著疑問,手動測試了一下。
比如得到下面的資訊是快照中的基準
BEGIN_SNAP   END_SNAP SNAPDATE             BEGIN_INTERVAL_TIME            END_INTERVAL_TIME              DURATION_MINS     DBTIME
---------- ---------- -------------------- ------------------------------ ------------------------------ ------------- ----------
     36202      36203 21 Aug 2015 07:00    21-AUG-15 06.00.59.625 AM      21-AUG-15 07.00.04.417 AM                 59        130
     36203      36204 21 Aug 2015 08:00    21-AUG-15 07.00.04.417 AM      21-AUG-15 08.00.09.642 AM                 60        139
     36204      36205 21 Aug 2015 09:00    21-AUG-15 08.00.09.642 AM      21-AUG-15 09.00.14.248 AM                 60        138
我們還是執行實時檢視DB time的指令碼來看看差別到底有多大,可以看到這個庫的負載情況比較規律,不會出現大的抖動,所以這個時間點範圍內的DB time應該還是在130左右。               
因為根據官方文件對於v$sys_time_model的描述,有個5秒的誤差或者延遲率。

V$SYS_TIME_MODEL displays the system-wide accumulated times for various operations. The time reported is the total elapsed or CPU time (in microseconds). Any timed operation will buffer at most 5 seconds of time data. Specifically, this means that if a timed operation (such as SQL execution) takes a long period of time to perform, the data published to this view is at most missing 5 seconds of the time accumulated for the operation.

我們就把測試的等待時間延長在5秒以上。
11:25:14 SQL> @aa.sql
    DBTIME   DURATION        PER
---------- ---------- ----------
 105969035 872180.533 121.498968
11:26:42 SQL> @aa.sql
    DBTIME   DURATION        PER
---------- ---------- ----------
 105969055 872180.717 121.498966
可以看到透過快照得到的負載是138/60=200%+
但是透過這個公式算出來的結果卻有些小了,在120%左右。
在其它的庫中也做了相似的測試,有的庫中差別小,有的庫中差別大。這個時候感覺指令碼的結果是飄忽不定,不準確了。
難道是v$sys_time_model用錯了
檢視這個檢視的定義,和使用dba_hist_sys_time_model還是有關係的。
Column Datatype Description
STAT_ID NUMBER Statistic identifier for the time statistic
STAT_NAME VARCHAR2(64) Name of the statistic (see Table 7-4)
VALUE NUMBER Amount of time (in microseconds) that the system has spent in this operation
那就可能是基準不對,如果例項啟動的startup_time不對,那麼該找哪個基準呢,能夠想到的只能是快照中的資料了。
我們可以嘗試以一個歷史快照為參考,透過比較最新的DB time值來進行負載的計算。
這個時候還需要依賴於dba_sys_time_model和dba_snapshots
這個時候重新改進的語句就是下面的形式。在rac下還沒有測試,單例項下還是沒有問題的。
select (e.value/1000000/60-temp.dbtime)/(((systimestamp+0)-(END_INTERVAL_TIME+0 ))*24*60) dbtime
from (select t.begin_interval_time,t.end_interval_time,t.snap_id,e.value/1000000/60 dbtime,e.stat_name
                        FROM DBA_HIST_SYS_TIME_MODEL e,dba_hist_snapshot t
                        WHERE
                         e.STAT_NAME = 'DB time'
                         and t.snap_id=e.snap_id
                         and t.begin_interval_time > sysdate-2/24
                         and rownum<2
                         ) temp,v$SYS_TIME_MODEL e
                         where e.STAT_NAME = 'DB time'
                         and rownum<2; 

rac環境:
  select (e.value/1000000/60-temp.dbtime)/(((systimestamp+0)-(END_INTERVAL_TIME+0 ))*24*60) dbtime
from (select t.instance_number,t.begin_interval_time,t.end_interval_time,t.snap_id,e.value/1000000/60 dbtime,e.stat_name
                        FROM DBA_HIST_SYS_TIME_MODEL e,dba_hist_snapshot t
                        WHERE
                         e.STAT_NAME = 'DB time'
                         and t.snap_id=e.snap_id
                         and t.snap_id =(select max(snap_id) from dba_hist_snapshot)
                         and e.instance_number=t.instance_number
                         and e.instance_number='1'
                         ) temp,gv$SYS_TIME_MODEL e
                         where e.STAT_NAME = 'DB time'
                         and temp.instance_number=e.inst_id

這個語句的重要控制點就在於時間的選擇,如果選擇3個小時前,2個小時前就會有一些差別,但是差別很小。可以說是誤差。
DB_NAME   BEGIN_SNAP   END_SNAP SNAPDATE             LVL DURATION_MINS     DBTIME
--------- ---------- ---------- -------------------- --- ------------- ----------
XXX          93464      93465 21 Aug 2015 00:00      1            30         15
               93465      93466 21 Aug 2015 00:30      1            30          5
               93466      93467 21 Aug 2015 01:00      1            30          5
比如這個庫的負載比較低,在20%以內,我們來看看3個小時前,2個小時前的基準,得到的DB time的情況。
3個小時前為基準:
    DBTIME_WORDLOAD
----------
       18%
2個小時前為基準:
    DBTIME_WORDLOAD
----------
       11%
和基準值差別不大,都是合理的範圍之內了。
其實這個問題的根本原因就在於取樣的範圍,參考的基準越近,得到的誤差範圍就越低。打個簡單的比方,就根據統計近年來的工資收入水平,我們還以解放前的標準來算,現在的誤差就會很大,而且不準確,以近些年來的情況來統計,結果就會在範圍之內,是一個基本可信的值了。

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

相關文章