Oracle10g为我们提供了,诊断和跟踪性能问题的绝佳方法。这些方法相比以前有了一些改进,新引入了9i中没有的新视图,比如
v$sess_time_model,v$session_wait_class,同时v$session视图的功能更加强大了。现在就来学习一下。呵呵:)
比如我做个实验造成一个锁等待
sess 1:
*********
SQL> select sid from v$mystat where rownum = 1;
SID
----------
525
SQL> select * from t;
ID NAME
---------- ----------
1 A
2 B
3 C
4 D
5 E
SQL> update t set name='e' where id=5;
1 row updated.
sess 2:
*********
SQL> select sid from v$mystat where rownum = 1;
SID
----------
532
SQL> update t set name='EE' where id=5;
此时这个session 532被hang住了。
在另外一个session我们来trace这个事件:
sess3:
**********
在Oracle 10g中v$session视图得到了极大的改进,引入了v$session_wait视图的一些功能。同时新增加了blocking_session这个column,表示某个session正在阻塞别人, 而且我们还可以根据wait_class这个列来对等待类别进行过滤
SQL> select sid,username,
event,
blocking_session,
seconds_in_wait,
wait_time
from v$session where state in ('WAITING')
and wait_class != 'Idle';
SID USERNAME
---------- ------------------------------
EVENT SECONDS_IN_WAIT
---------------------------------------------------------------- ---------------
WAIT_TIME
----------
532 SYS
enq: TX - row lock contention 71536
0
sess1的sid是525,sess2的sid是532,那么结果表明,sid 532被blocking_session 525给blocked住了,以一种TX事务锁的方式block
也就是说SID 525会话正在等待一个表上的事务锁的释放,而这个锁正由532会话(BLOCKING_SESSION)占用。
现在我又想知道是那个SQL语句导致了这个锁的占用也就是说,525这个session在执行什么SQL,hold住了我们的事务锁,那么我们可以通过连接V$SESSION和V$SQL这两个视图执行下面的查询很容易地找到答案:
SQL> select sid, sql_text
from v$session s, v$sql q
where sid in (532,525)
and (q.sql_id = s.sql_id or q.sql_id = s.prev_sql_id);
这里我们用到了sql_id这是10g推出的一种唯一标识SQL语句的列,通过他我们可以唯一标识我们的sql
SID
----------
SQL_TEXT
---------------------------------------------
525
update t set name='e' where id=5
532
update t set name='EE' where id=5
532
select sid from v$mystat where rownum = 1
我们看到两个会话都试图更新同一行。除非会话525提交或回滚,否则会话532将一直等待这个锁。
以上就是我们的会话等待的检索方法。
在10g之后还提出了等待类的概念:
并且推出了新的视图v$session_wait_class
我们来看一下session 532的等待类
SQL> select wait_class_id,wait_class,total_waits,time_waited
from v$session_wait_class
where sid=532;
WAIT_CLASS_ID WAIT_CLASS
------------- ---------------------
TOTAL_WAITS TIME_WAITED
----------- -----------
4217450380 Application
23863 6986631
2723168908 Idle
6 38227
2000153315 Network
6 0
还是继续上面的测试,我们知道sid=532一直在等待sid=525的会话,在这个结果中,显示了每个类中会话的等待事件的次数,还有等待的时间,我们看到application这一级别中,的等待次数是876,而time_waited时间是69866.31秒(原来的6986631单位是厘秒单位,百分之一秒).那么这个时候我们还可以从application等待类中寻找引起等待的原因。
v$system_event视图中我们可以获得每种等待的出现次数。我们这里的application的id为4217450380
SQL> select event,total_waits,time_waited
2 from v$system_event e,v$event_name n
3 where n.event_id=e.event_id
4 and n.wait_class_id=4217450380;
EVENT TOTAL_WAITS
---------------------------------------------------------------- -----------
TIME_WAITED
-----------
enq: RO - fast object reuse 51
1
enq: TX - row lock contention 23891
6994835
SQL*Net break/reset to client 34
0
我们可以看到在这个application等待类中锁的争用占了大部分的时间。
假如我们并不知道是什么原因,导致了这个锁的争用,那我们该怎么去定位这个TX-row lock contention的问题呢?这些数据仅仅告诉了我们ok,用户经历了23891次的锁的竞争,共花费了6994835厘秒,有可能大多数的等待只有1到2厘秒,那么如何在进行进一步的诊断呢?
Oracle 10g还为我们提供了另外一个视图叫v$event_histogram
它标市了等待时间的周期以及会话等待某一特定时间周期的频度
select wait_time_milli,wait_count
from v$event_histogram
where event='enq: TX - row lock contention';
WAIT_TIME_MILLI WAIT_COUNT
--------------- ----------
1 0
2 0
4 0
8 0
16 0
32 0
64 0
128 0
256 4
512 13
1024 0
2048 0
4096 23896
v$event_histogram视图显示等待时间段以及在这期间会话等待某一特定事件--在这个例子中就是事务锁争用--的次数。例如,会话等待少于4096毫秒(ms)的事件共23532次,等等。WAIT_COUNT列值之和为23904.v$event_histogram视图显示,大多数等待发生在256毫秒、512毫秒和4096毫秒的事件上,这就充分证明了该应用程序正在经历锁的争用问题,如果视图显示等待发生在1毫秒的范围内,我们就不应该认为这是锁争用的问题,因为这样短时间的等待似乎是正常的。
Oracle 10g还推出了一种时间模型的概念:
比如我们经常会遇到有人抱怨某某sid的会话非常的慢.这个时候,我们首先可以通过v$session来查看。
首先我们可以监控出当前的活动session
SQL> select sid,username,status from v$session
where status='ACTIVE' and username is not null;
SID USERNAME STATUS
---------- ------------------------------ --------
526 SYS ACTIVE
532 SYS ACTIVE
538 IRMADMIN ACTIVE
那么我的业务session就是536了,通过 v$session视图查看
select event,seconds_in_wait,wait_time
from v$session
where sid= 538
EVENT SECONDS_IN_WAIT
---------------------------------------------------------------- ---------------
WAIT_TIME
----------
db file sequential read 0
1
我们看到sid=538有个等待事件,这样我们再来通过v$sess_time_model来估量一下,这个会话对资源的利用是否格外的高
SQL> select stat_name,value
2 from v$sess_time_model
3 where sid=538;
注意这些单位都是微秒一级的(1/1000000)
STAT_NAME VALUE
---------------------------------------------------------------- ----------
DB time 2950266754
DB CPU 2766530454
background elapsed time 0
background cpu time 0
sequence load elapsed time 8898
parse time elapsed 32700260
hard parse elapsed time 31590611
sql execute elapsed time 2908768149
connection management call elapsed time 2428
failed parse elapsed time 0
failed parse (out of shared memory) elapsed time 0
hard parse (sharing criteria) elapsed time 63296
hard parse (bind mismatch) elapsed time 63296
PL/SQL execution elapsed time 24049473
inbound PL/SQL rpc elapsed time 0
PL/SQL compilation elapsed time 21250121
Java execution elapsed time 902194
repeated bind elapsed time 18060
RMAN cpu time (backup/restore) 0
那么在检查数据库性能的时候,有的时候我们还需要检查操作系统一级的状态,那么在Oracle 10g之前呢,操作系统的工具比如OS,vmstat等工具,通过他们来确定一些争用问题的度量指标,在Oracle 10g中,我们可以在数据库中自动采集OS级别的度量指标,可以查看主机的一些潜在的主机争用问题
SQL> select stat_name,value from v$osstat;
这些单位都是厘秒一级的(1/100)
STAT_NAME VALUE
---------------------------------------------------------------- ----------
NUM_CPUS 4
IDLE_TIME 34370136
BUSY_TIME 1427854
USER_TIME 1349492
SYS_TIME 78323
IOWAIT_TIME 209146
AVG_IDLE_TIME 8591041
AVG_BUSY_TIME 355613
AVG_USER_TIME 336469
AVG_SYS_TIME 18334
AVG_IOWAIT_TIME 50465
OS_CPU_WAIT_TIME 1446100
RSRC_MGR_CPU_WAIT_TIME 0
LOAD .005859375
NUM_CPU_CORES 2
NUM_VCPUS 2
NUM_LCPUS 4
PHYSICAL_MEMORY_BYTES 4026531840
系统的一个CPU有34370136厘秒空闲(IDLE_TIME)、1427854厘秒繁忙(BUSY_TIME),这表明CPU有大约4%的时间繁忙。可以得出结论,在主机中CPU不是瓶颈。请注意,如果主机系统有多于1个的CPU,则标头中有AVG_前缀的列,如AVG_IDLE_TIME将显示所有CPU的这些度量指标的平均值。
有一种情况,当我们查询v$session视图的时候,会话是空闲的,可能没有正在等待的事件,那么我们如何来诊断这个会话 出现问题的时候是在等待什么会话呢?
Oracle 10g在内存的缓冲区中每秒采集一次我们活动会话的信息,这个缓冲区被称为活动会话历史(Active session history,ASH),我们可以在v$active_session_history这样一个动态性能视图中查看他,其中的数据可以保留30分钟,那么我们在得到了sid和serial#后就可以查询v$active_session_history来找到我们会话过去的等待事件。
SQL> select sample_time,event,wait_time
2 from v$active_session_history
3 where session_id=538 and session_serial#=11197 and event is not null;
SAMPLE_TIME
---------------------------------------------------------------------------
EVENT WAIT_TIME
---------------------------------------------------------------- ----------
19-JAN-08 12.46.42.757 PM
direct path read temp 0
19-JAN-08 12.46.23.746 PM
db file sequential read 0
19-JAN-08 12.46.22.745 PM
db file sequential read 0
这样我们就跟踪出历史的等待事件信息:
通过联合查询v$sql视图我们可以查看到具体时间等待事件的sql语句:
这里我们查看direct path read temp等待事件的sql信息
select sql_text ,application_wait_time
from v$sql
where sql_id in
(select sql_id from v$active_session_history
where sample_time='19-JAN-08 12.46.42.757 PM' and session_id=538
and session_serial#=11197);
那么其中application_wait_time表示执行这个SQL的会话等待了多长时间的application的等待类。
如果ash的内容30分钟后被清除了,那么这些数据并没有丢失而是送到了AWR这样一个工作负载库中去了。这个库的内容可以从dba_hist_active_session_hist中看到。在默认的情况下这个视图的内容也只保留7天。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12361284/viewspace-153354/ ,如需转载,请注明出处,否则将追究法律责任。