前言
在处理被ADDM捕捉的突发的性能问题中,10g等待接口提供非常有价值的数据用于诊断。作为一个DBA,你可能遇到过很多次用户抱怨“数据库非常慢了”。那么你是如何定位这种问题的呢?你第一步要做的肯定是查看是否有会话在等待数据库内部或外部的什么资源。
Oracle提供了一个简单但是又很有效的机制来获取这些信息:视图V$SESSION_WAIT。这一视图提供了各种信息以帮助诊断如一个会话正在等待和已经等待的事件、及等待了多少、等待时间多长。例如,如果会话正在等待事件“db file sequential read”,字段P1和P2就标识会话正在等待的数据块的file_id和block_id。
对于大多数等待事件来说,这个视图已经足够了。但由于以下两个原因,它很难成为一个强有力的优化工具:
· 这个视图只是当前状态的一个快照。当等待不存在了,会话早前关于这些等待的历史信息也没有了,使事后诊断分析变得很困难。
V$SESSION_EVENT视图提供了累积的但不够详细的数据。
· V$SESSION_WAIT视图仅包含了等待事件的信息。要获取其他相关信息如USERID和终端信息就必须和视图V$SESSION连接查询。
在Oracle 10g中,等待接口从根本上被重新设计了,提供了更多的信息,而且减少了DBA的干预。在这篇文章中,我们将探索这些特性,看看它们如何帮助我们来诊断性能问题。对于大多数性能问题,你能从ADDM中得到扩展的分析信息,但是ADDM没有捕捉到哪些即时问题的信息。而等待接口提供了非常有用的数据用于诊断。
增强的会话等待
首先一个增强就是对视图V$ESSION_WAIT本身的。这可以从一个例子来解释。加入您的用户抱怨会话被hang住了。你查出这个会话的SID,并从视图V$SESSION_WAIT中找出这个SID的记录。以下就是输出内容:
请注意哪些黑体字段。在这些字段中,WAIT_CLASS_ID、WAIT_CLASS#和WAIT_CLASS字段是10g中新增的。字段WAIT_CLASS表示这个等待的类型是一个有效的等待事件还是一个可以被忽略的空闲等待事件。在上面的例子中,等待类型是”Application”,表明它在等待你的干预。SID : 269 SEQ# : 56 EVENT : enq: TX - row lock contention P1TEXT : name|mode P1 : 1415053318 P1RAW : 54580006 P2TEXT : usn<<16 | slot P2 : 327681 P2RAW : 00050001 P3TEXT : sequence P3 : 43 P3RAW : 0000002B WAIT_CLASS_ID : 4217450380 WAIT_CLASS# : 1 WAIT_CLASS : Application WAIT_TIME : -2 SECONDS_IN_WAIT : 0 STATE : WAITED UNKNOWN TIME
这一字段让你更加明确哪些字段可以用于调优。例如,你可以用以下查询来获取等待这个事件的会话:
在这你可以看到几个事件(如Queue Monitor Wait和JobQueue Slave)被明确标注为Idle事件。你可以把它们视为非阻塞等待忽略掉。但是,有时候这些”idle”事件预示着一个内部问题。例如,与SQL*NET相关的事件可能预示网络可能出现潜在问题。SQL> select wait_class, event, sid, state, wait_time, seconds_in_wait 2 from v$session_wait 3 order by wait_class, event, sid 4 / WAIT_CLASS EVENT SID STATE WAIT_TIME SECONDS_IN_WAIT ---------- -------------------- ---------- ------------------- ---------- --------------- Application enq: TX - 269 WAITING 0 73 row lock contention Idle Queue Monitor Wait 270 WAITING 0 40 Idle SQL*Net message from client 265 WAITING 0 73 Idle jobq slave wait 259 WAITING 0 8485 Idle pmon timer 280 WAITING 0 73 Idle rdbms ipc message 267 WAITING 0 184770 Idle wakeup time manager 268 WAITING 0 40 Network SQL*Net message to client 272 WAITED SHORT TIME -1 0
另外一个需要注意的重要信息就是字段WAIT_TIME的值是-2。一些平台,如Windows,不支持快速计时机制。如果在哪些平台上,初始化参数TIMED_STATISTICS没有设置为on,就无法检测到精确的计时统计。在那样的情况下,在Oracle9i中,这个字段的值是一个非常大的值,它会让以后的问题定位产生混乱。在10g中,值-2就表示是这种情况——平台不支持快速计时机制并且TIME_STATISTICS被设置为off。 会话也会显示等待信息
还记得前面说需要将视图V$SESSION_WAIT和V$SESSION连接查询来获取关于会话的细节信息吗?在10g中,这将成为历史。10g中的视图V$SESSION也会显示和V$SESSION_WAIT一样的等待事件信息。以下便是V$SESSION用于显示会话当前所等待的等待事件而新增的字段。
这些字段和V$SESSION_WAIT中的是一样的,并且显示的信息也相同。这样就无需再查询V$SESSION_WAIT视图了,要获取到会话的等待信息就只需要查询一个视图就行了。EVENT# NUMBER EVENT VARCHAR2(64) P1TEXT VARCHAR2(64) P1 NUMBER P1RAW RAW(4) P2TEXT VARCHAR2(64) P2 NUMBER P2RAW RAW(4) P3TEXT VARCHAR2(64) P3 NUMBER P3RAW RAW(4) WAIT_CLASS_ID NUMBER WAIT_CLASS# NUMBER WAIT_CLASS VARCHAR2(64) WAIT_TIME NUMBER SECONDS_IN_WAIT NUMBER STATE VARCHAR2(19)
让我们看看前面这个例子:SID为269的会话正在等待事件enq: TX ?C row lock contention。这表示它正在等待另外一个会话持有的锁。要诊断这个问题,你就必须定位到另外一个会话。如何做呢?
在9i和以下版本中,你可能需要写一个复杂的查询来获取到持有锁的会话的SID。在10g中,你就只需要执行以下查询就可以了:
这个结果说明:SID为265的会话阻塞了会话269。SQL> select BLOCKING_SESSION_STATUS, BLOCKING_SESSION 2 from v$session 3 where sid = 269; BLOCKING_SE BLOCKING_SESSION ----------- ---------------- VALID 265
有多少等待?
有一个用户的会话一致在保持着,他的问题还没有得到满意的解决。为什么他的会话会保持这么长事件还没有完成呢?你可以通过以下查询来定位:
请注意关于这个会话等待的诸多信息。现在你就知道了这一会话已经等待和应用相关的等待事件共873次、261537厘秒,等待网络相关的事件15次,等等。 用同样方法,你可以通过以下查询获取到整个系统范围的等待事件分类的统计信息,时间单位还是厘秒:SQL> select * from v$session_wait_class where sid = 269; SID SERIAL# WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS TOTAL_WAITS TIME_WAITED ---- ------- ------------- ----------- ------------- ----------- ----------- 269 1106 4217450380 1 Application 873 261537 269 1106 3290255840 2 Configuration 4 4 269 1106 3386400367 5 Commit 1 0 269 1106 2723168908 6 Idle 15 148408 269 1106 2000153315 7 Network 15 0 269 1106 1740759767 8 User I/O 26 1
大多数问题的发生都不是孤立的。在它们背后还存在一些其他问题,这些问题可以通过一种样式来定位。这一样式可以通过以下查询语句来查询一个历史视图来获得:SQL> select * from v$system_wait_class; WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS TOTAL_WAITS TIME_WAITED ------------- ----------- ------------- ----------- ----------- 1893977003 0 Other 2483 18108 4217450380 1 Application 1352 386101 3290255840 2 Configuration 82 230 3875070507 4 Concurrency 80 395 3386400367 5 Commit 2625 1925 2723168908 6 Idle 645527 219397953 2000153315 7 Network 2125 2 1740759767 8 User I/O 5085 3006 4108307767 9 System I/O 127979 18623
请注意字段WAIT_CLASS_ID和他的统计数据。对于值4217450380,我们发现有2个会话在等待这一类型的事件共5次、1499厘秒。但是这一类型等待是什么等待事件呢?你可以从视图V$SYSTEM_WAIT_CLASS中得到这个信息。如上所示,这是Application类型事件。SQL> select wait_class#, wait_class_id, 2 average_waiter_count "awc", dbtime_in_wait, 3 time_waited, wait_count 4 from v$waitclassmetric 5 / WAIT_CLASS# WAIT_CLASS_ID AWC DBTIME_IN_WAIT TIME_WAITED WAIT_COUNT ----------- ------------- ---- -------------- ----------- ---------- 0 1893977003 0 0 0 1 1 4217450380 2 90 1499 5 2 3290255840 0 0 4 3 3 4166625743 0 0 0 0 4 3875070507 0 0 0 1 5 3386400367 0 0 0 0 6 2723168908 59 0 351541 264 7 2000153315 0 0 0 25 8 1740759767 0 0 0 0 9 4108307767 0 0 8 100 10 2396326234 0 0 0 0 11 3871361733 0 0 0 0
再注意DBTIME_IN_WAIT这一非常有用的字段。你也许还记得在10g的AWR中会在很细的粒度下记录下数据库的消耗时间。DBTIME_IN_WAIT就表示数据库消耗的等待时间。跟踪
当用户的问题解决后,你可能还要继续跟踪有什么其他不同的等待事件导致了他的问题。当然,你可以很轻松的通过查询V$SESSION_WAIT视图来获取答案。但是很不幸,这些等待事件都已经不存在了。因此也就没有它们的记录了。这时要如何做?
在10g中,视图V$SESSION_WAIT_HISTORY会自动记录下活动会话等待的最近10次的等待事件历史信息。要查找这些事件,只要执行以下语句:
当会话停止或连接断开后,视图中的这些记录就没有了。然而,这些等待的历史信息会被维护在AWR表中以便以后的分析。查询这些会话等待的AWR视图是V$ACTIVE_SESSION_HISTORY。SQL> select event, wait_time, wait_count 2 from v$session_wait_history 3 where sid = 265 4 / EVENT WAIT_TIME WAIT_COUNT ------------------------------ ---------- ---------- log file switch completion 2 1 log file switch completion 1 1 log file switch completion 0 1 SQL*Net message from client 49852 1 SQL*Net message to client 0 1 enq: TX - row lock contention 28 1 SQL*Net message from client 131 1 SQL*Net message to client 0 1 log file sync 2 1 log buffer space 1 1
总结
由于10g的这些增强特性,分析性能问题变得十分简单。关于会话等待的历史信息帮助你诊断会话结束以后发生的问题。对等待的分类可以帮助你理解每个等待的重要性。
来源:WWW.HelloDBA.COM