原文地址:http://tech.e2sn.com/oracle-scripts-and-tools/session-snapper
原文作者:[Tanel Poder]
引言
? Oracle Session Snapper v3相比較之前的版本(V2,V1)有很大的改進,除了獲取各種 v$和 x$性能視圖的快照和報告增量外,還從 v$session中抽取會話詳細信息,這很像 Oracle 的 Active SESSION History 所做的統計采樣(ASH 本質上只是一個 v$SESSION 的采樣)。但是,使用 ASH 需要有額外的診斷程序包許可證,而查詢 v $SESSION則不需要 (Snapper工具 就是做這樣的事情),從3.52版本開始,Snapper 還支持 Oracle 9.2上的 ash- 樣式的采樣(在以前的版本中需要 Oracle 10g +)。
? Oracle Session Snapper v3可以對v$SESSION 的 進行ASH 風格的采樣, 現在可以報告 TOP 會話、 TOP wait 事件、 TOP SQL id、TOP pl/SQL 過程等。
? 盡管在 Oracle Session Snapper 中使用 ASH 風格的抽樣,但它并不是 Oracle (獨立授權的) ASH。這只是相同的概念,但不同的工具。Snapper 所做的只是使用普通的 PL/SQL 塊對 v$SESSION 視圖進行抽樣,因此 Oracle 提供了免費的服務。
? Snapper 是一個快速、簡單的性能故障排除工具,適用于那些在數據庫出現問題時親自動手(并快速修復問題)的運維dba。Snapper 是一個靈活的第一輪性能故障排除工具,這是一個用于故障排除的入口工具,你可以在幾秒鐘內輕松地運行它,而不必立即采用諸如 SQL 跟蹤等繁重的操作。
? Snapper不會為你解決問題,它不提供任何智能性能建議,也不提供任何調優建議。它所做的就是展示信息。它將從 v$SESSTAT 等視圖獲取快照數據,并顯示在快照期間某個會話的性能計數器增加了多少。Snapper v3還會顯示在快照期間采集的活動 v$SESSION 樣本的 TOP 報告,就像 ASH 那樣
以下是關于 Snapper 的一些重要說明:
1、不在數據庫中創建任何對象
2、只是一個匿名的 PL/SQL 塊,可以動態地解析和編譯
3、不會對數據庫用戶做任何更改
請注意,你現在正在閱讀的這個文章并不是一個完整的系統性能故障排除指南,只是Session Snapper 工具的功能介紹。
使用Snapper工具
在下面示例中,假設你已經能夠找出運行緩慢的會話(或作業運行緩慢)的 SID。假設它是140,那么你可以像這樣運行 Snapper:

如果你對Snapper使用不清楚,下面介紹它的4個重要參數:
1、參數1(ash) 抽樣類型
- 在 Snapper v3中,你可以使用“ ASH”進行活動會話歷史記錄樣式的抽樣
- 在早期版本和v3版本中,你可以使用“ STATS”來獲取 v$SESSTAT 和其他性能計數器的快照
2、參數2(5) 快照的間隔周期
- 在示例中,Snapper每5秒統計,然后打印報告
3、參數3(1) 快照的統計次數
- 第一次診斷時,通常只使用一個快照/報表,但有時會使用更大的數字來獲取多個快照和報表
4、參數4(140) 需要獲取快照的會話SID
- 只指定一個會話,如140
- 指定多個會話,逗號隔開,如140,141,142
- 使用ALL指定所有會話
- 可以使用user=SYSTEM or program=sqlplus or module=HR
- 也可以使用子查詢,類似select sid from v$session where username=‘SYSTEM’ and program not like ‘sqlplus%’"
Snapper工具的ASH模式使用
實例內單一會話運行的ASH模式
示例1
假設我們已經知道運行緩慢的會話SID 10,在 ASH 模式下運行 snapper,快照長度為5秒,一次在 SID 10上:

輸出非常簡單:
- Active% (%Thread,版本差異顯示略有不同) 在采樣的時間內,此會話花費的多少時間來相應執行輸出行上列出的操作
- 100% 表明會話10一直在執行bu24rz6yy2vn1這個SQL
- enq: TX - row lock contention 代表會話在快照的5s內一直處于這個狀態
由于 Snapper 的 ASH 功能(就像 ASH 本身一樣)是通過定期采樣 v$SESSION (類似于從其中獲取快照)來工作的,所以它并不能捕獲會話所做的每一件事。然而,它確實捕捉到了所有有意義的信息。
例如,我們不能完全確定這個會話是否真的100% 地執行了上面提到的操作,也許它只是忙于運行 SQLID,并且只有99% 的響應時間在等待該事件,并且在1% 的時間里執行了其他操作。Snapper 可能只是錯過了另外1% 的采樣,因為這個“其他”的事情發生得太快,在兩個樣本之間,所以它沒有被捕獲。然而,當一些事情發生的頻率很低,而且發生的很快,以至于它甚至沒有被記錄在許多樣本中的一個樣本中,那么它就不能太重要了!如果某件事占用了50% 的響應時間,那么肯定會有一些樣本(大約占總數的一半)顯示“某件事”正在發生。
? Snapper 報告輸出的底部顯示快照周期何時結束,在此期間完成了多少秒的采樣以及完成了多少 v$SESSION 采樣。上面我們看到 Snapper 在5秒鐘內采集了45個 ASH 樣本(每秒超過8個樣本)。Snapper 的編寫方式是,當快照周期很短時(最長可達10秒) ,采樣速度非常快,但在快照周期較長時降低采樣頻率,以減少測量開銷。在很長一段時間內,采樣頻率將是1赫茲,就像 ASH 一樣每秒一次采樣。
? 繼續上面的示例,我們已經確定會話10一直在等待鎖。我們現在可能想知道是誰在阻止我們,以及我們試圖鎖定的是哪種資源。在出現隊列鎖等待的情況下,等待事件附加細節列(Parameter2,3)將為我們提供關于我們試圖鎖定的對象/資源的附加信息(查看 v$LOCK 類型以了解其含義)。所以我們想要采集P2,P3從 v$SESSION 獲得更多關于這個等待的詳細信息。此外,在排隊等待的情況下,我們可以示例 v $SESSION BLOCKING_SESSION 阻塞會話以查看哪個會話阻塞了我們。
? 因此,我不必依賴默認的 ASH TOP 活動分組,而是可以使用**ASH=**語法,請注意,并非所有的 v$SESSION 列在 Snapper 中都可用,但是最重要的是。我只需要指定我想取樣的列的列表,列表之間用+分割。

現在我們可以看到更多的信息。阻塞的 SID 是140,我們正在等待的鎖定對象的對象 ID 是1048579
上面的示例并沒有真正顯示 Snapper 的分析能力,因為會話被卡住,運行相同的語句,等待相同的事情。
示例2
另外一個例子:

? 顯然,在這種情況下,會話并不是只等待單個等待事件,它運行的 SQL 與 TOP 會話活動報告中的所有 SQL ID 是相同的,但是在執行該 SQL 期間,會話有不同的等待事件,并且也花費了一些時間在 CPU 上。請注意,該會話的 CPU 使用率僅在 Snapper 運行期間為28% ,剩余響應時間的72% 都用于物理 IO 相關的等待事件(36% + 33% + 3%)。
? 因此,在對該會話的性能進行故障排除時,我已經知道100% 的響應時間(至少在 snapper 運行期間)用于使用 ID 執行 SQL3jbwa65aqmkvm 執行過程本身等待了72% 的時間用于 i/o。
示例3

? 在這種情況下,看起來在5秒快照運行期間執行了許多不同的語句。TOP SQL是一個至少30% 的時間處于活動狀態(db file sequential read)。
? 由于報告了多個不同的語句,所有這些語句都占用了大量的響應時間——這都是因為 User i/o 等待事件,這可能是調查 IO 子系統問題的一種情況(突然之間所有語句都報告了 SQL i/o 等待)。
? 注意:還有一個更有重要的事情要看,Active% 為54% 。這意味著在采樣期間這個會話只有54% 是活躍,因此,其余時間它是空閑的,通過網絡,等待來自應用程序的下一個請求。如果你發現數據庫會話只有很少一部分時間處于活動狀態,那么對數據庫中的任何內容進行優化都是沒有意義的——你需要了解為什么應用程序向數據庫發送新請求的速度不夠快。
? 會話出現空閑的原因很多:
- 用戶思考時間,用戶請求頻率不高。
- 應用思考時間。當應用程序服務器超載或者有一些錯誤的代碼時,經常會發生這種情況。應用程序非常繁忙或陷入僵局,因此無法將請求發送到數據庫并快速處理結果數據
- 網絡延遲和吞吐量。把它放在最后,因為看用戶和應用程序實際在做什么是有意義的,而不是立即假設問題一定是在網絡中
? 請注意,正如我前面所說的,Snapper 是一個為你提供信息和性能數據的工具。它不會為你提供性能建議,你仍然需要遵循一個系統的方法進行故障排除和調優,Snapper 是支持它的工具。
? 所以,這就是所有的單個會話快照,但是,Snapper 可以做更多。
? 有時候你需要測量多個會話,有時候你甚至不知道 SIDs,有時候你需要看到整個實例活動。可以看下面的使用
實例內全部會話運行的ASH模式
使用 snapper 來度量所有會話的活動很容易,你只需指定all,不需要指定具體的sid

Active% 仍然顯示一個會話的響應時間!如果兩個會話的所有響應時間都在等待一個鎖,那么你會看到200% 的等待時間。
如果我想分解有多少個會話正在等待某個事件,我可以添加sid 返回一個參數,如下所示,現在用于 TOP 報告的組由 SID、 event 和 wait _ class 完成:

SID 133是95% 的響應時間都在等待db file scattered read,剩下的5% db file sequential read . 在 IO 操作之間偶爾的 CPU 使用是如此短暫,以至于 Snapper 的 v$SESSION 抽樣甚至沒有看到它,換句話說,這個會話在 Snapper 運行期間沒有顯著地使用 CPU。
使用 Snapper 獲取多個會話活動報告
如上所述,有時候,僅僅一個報告可能是不夠的。你可能希望從多個不同的角度查看會話/實例活動數據(按不同的字段對 ASH 示例進行分組)。這就要使用Snapper 的ash1, ash2 及ash3 語法,你可以顯示最多4 個ASH TOP 活動在一個 Snapper 運行。例如,假設我想通過 PL/SQL 包中的 object _ ID 和過程 ID 來分解會話活動,以查看是否有某個 PL/SQL 包導致了大部分工作(這些列可從 v$SESSION 中的10.2.0.3獲得) 。

假設我想再加入一個報告,它向我展示了來自會話program, module 和action字段:

上面所有的東西都可以在 Snapper v3中找到。然而,這只是 Snapper 全部能力的一部分。有時僅僅知道 TOP sql_id 和 wait 事件是不夠的。考慮一下這樣的情況: 會話100% 使用 CPU,不等待任何事情,SQL 執行計劃也沒有明顯的錯誤。這是你想知道session在做什么,這就到了 Oracle 的動態性能計數器發揮作用的地方——我主要談論 v$SESSTAT 統計數據。
Snapper工具基于V$性能統計
? 自從版本V1之后,Snapper 就有了統計模式。這就是為什么我最初編寫 Snapper,來幫助我進行性能故障排除,特別是在像 SQL 跟蹤或者像 AWR/Statspack 這樣的實例級性能工具沒有顯示任何有用信息的情況下。從 v3開始,Snapper 不會自動顯示 v$SESSTAT 的統計數據,因為 Snapper 現在也被用作一個實例范圍的故障排除工具(而且在實例中有數千個會話時,查詢所有會話的 v$SESSTAT 可能會非常昂貴)。
? 因此,如果你想深入了解 v$SESSTAT 示例,你需要使用stats 參數進行統計, Snapper 從v$SESSTAT 和其他 v $視圖的獲取快照。也可以使用all(代表ash 和stats)
另外,你可以指定要捕獲的統計類型,利用gather 選項
選項如下:
Session-level stats:
s - Session Statistics from gv$sesstat
t - Session Time model info from gv$sess_time_model
w - Session Wait statistics from gv$session_event and gv$session_wait
Instance-level stats:
l - instance Latch get statistics ( gets + immediate_gets )
e - instance Enqueue lock get statistics
b - buffer get Where statistics – useful in versions up to 10.2.x
a - All above
如果啟用了stats ,但是沒有使用gather ,那么僅僅在會話級統計(s,t,w)
在實例級運行Snapper工具
例如,我從所有會話中獲取 ash session 活動快照,但是我也要求 Snapper 收集 Time Model Stats (t)和 v $SESSTAT Stats (s) ,但是只包括 Time Model Stats (tinclude) ,其名稱中包含字符串% CPU% ,只包含 v $SESSTAT (sinclude) ,其中包含單詞% parse% :

在上面輸出的上半部分,可以 Snapper 的統計模式中會話133,每秒2.25千硬解析(這是一個很大的!).我可以使用 v$SESSTAT 中提供的任何其他統計數據(在 Oracle 11.2中,每個會話有600多個不同的統計數據)。例如,如果我在sinclude 參數中使用"redo size",我將很容易看到哪個會話生成最多的重做日志。
另一件要注意的事情是,下面的 ASH 部分說有 CPU 活動值為單個會話響應時間的105% (這意味著必須有一個以上的會話使用該 CPU) ,上面的時間模型統計(stats type = TIME)根本沒有報告顯著的 DB CPU 使用情況。這里的問題是度量粒度。時間模型統計數據僅在數據庫調用結束時在v$視圖中更新,但是如果數據庫調用是長時間運行的(如我的測試案例) ,那么 V$SESS_TIME_MODEL中的統計數據默認情況下大約每5秒更新一次。由于我的 Snapper 運行時間很短(5秒) ,腳本顯然在V$SESS_TIME_MODE更新發生在長時間運行的數據庫調用會話之前就完成了。如果你用更長的采樣時間運行 snapper,比如60秒,你應該看到所有時間模型的統計數據。
到目前為止,我們已經介紹了如何在一個會話或整個實例上運行 snapper。有時候,你需要監視特定用戶、服務或程序的所有會話。這在 Snapper 中也是可以的
在會話級運行Snapper工具
從 v3開始,Snapper 有方便的方法來指定user, application, service等信息。例如,你可以直接編寫 user = ,而不是將第4個參數指定為 SID。

由于上面指定的參數(ash 和 ash1) ,我們得到了同一個會話活動數據的不同細分,我們只測量了屬于用戶 SOE 的會話。
可以指定其他參數:
- username (same as user)
- sid
- spid (same as pid and ospid)
- program
- machine
- osuser
- module
- action
- client_id
但是,你不能將這些參數組合成任何 AND 或 OR 條件,你只能使用上述方便的語法一次傳遞一個參數。
然而,如果你想要非常精確地知道哪些會話 Snapper 監視器(如果你想要添加多個和/或條件來選擇感興趣的會話) ,那么你可以用老方法來選擇會話

你可以在雙引號之間編寫任何子查詢作為 SID 參數,只要它適合于命令行并返回一個帶有 SID 列表的數字列即可
下載Snapper工具
可以通過以下地址下載
https://github.com/tanelpoder/tpt-oracle/blob/master/snapper.sql
更多文章參考
你可以在我的博客上看到所有與 snapper 相關的文章:
反饋
我很多年前就寫了初版的 Snapper,但我仍然不清楚有多少人真正在使用它,以及他們是如何使用它的,所以如果 Snapper 過去曾經幫助過你(或者現在正在幫助你) ,那么請給我發一封電子郵件,告訴我你是如何使用它的




