技术开发 频道

用Oracle10中的等待界面诊断性能问题

    【IT168 技术文档】

    John是Acme银行的数据库管理员,电话另一端是愤怒的用户Bill,他抱怨他的数据库会话被挂起来了,对这种抱怨大多数数据库管理员是再熟悉不过了。John怎么才能打消Bill的抱怨呢?

    Acme银行的数据库是Oracle数据库10g,因此John有很多种选择。自动数据库诊断管理器(ADDM)是Oracle数据库10g的新特性,它可以告诉John数据库当前的整体状态和性能,因此John一开始就用ADDM来确定Bill的会话正在经历的是否是数据库范围内的问题。ADDM报告确认没有能对Bill的会话产生这种影响的数据库范围内的问题,因此John继续考虑下一种选择。

    一种诊断会话级事件(如Bill的问题)的方法就是确定会话是否正在等待什么事件,如文件块的读操作或表行上的锁或栓。从Oracle7开始,Oracle就提供了多种机制来显示数据库内发生的等待,而且在最近几年里,这一产品在不断地完善,加入了越来越多的诊断信息。在Oracle数据库10g中,提供了经过重大改进的等待事件信息,使诊断一个会话的速度减慢的问题变得更加容易。本文告诉你如何使用Oracle数据库10g中的等待事件来确定瓶颈问题。

    会话等待

    数据库管理员John如何才能确定是什么引起了Bill的会话挂起呢?实际上,会话并没有挂起;它正等待一个事件的发生,而这正是John要检查的。

    John要继续其调查可以使用Oracle企业管理器或者直接通过命令行访问V$视图。John有一套用于诊断这些类问题的脚本,因此他使用命令行。

    John查询V$SESSION视图来看一下Bill的会话正在等待什么。(请注意John过滤掉了所有空闲事件。)

select sid, username, event, blocking_session, seconds_in_wait, wait_time from v$session where state in ('WAITING') and wait_class != 'Idle';

    下面以垂直格式给出输出结果。

    SID : 270
    USERNAME : BILL
    EVENT : enq: TX - row lock
    contention
    BLOCKING_SESSION : 254
    SECONDS_IN_WAIT : 83
    WAIT_TIME : 0

    看到这些信息,John立刻得出结论,Bill的SID 270会话正在等待一个表上的锁,而这个锁正由254会话(BLOCKING_SESSION)占用。

    但是John想知道哪条SQL语句引起了这个锁的占用。他可以通过连接V$SESSION和V$SQL视图执行下面的查询很容易地找到答案:

select sid, sql_text from v$session s, v$sql q where sid in (254,270) and ( q.sql_id = s.sql_id or q.sql_id = s.prev_sql_id);

    John看到(在清单1中)两个会话都试图更新同一行。除非会话254提交或回滚,否则会话270将一直等待这个锁。他向Bill解释了这一切,而Bill现在也不那么生气了,他认为应用程序中的有些东西出了问题,因此要求John结束会话254,以释放锁。

    等待类

    John结束了妨碍Bill的会话后,Bill的会话可以继续进行但是很慢。John决定检查该会话中的其他问题。他又一次检查看是否有任何其他等待事件,但这次他特别检查Bill的会话。

    在Oracle数据库10g中,等待事件根据事件的类型分为不同的等待类。将事件分组使你能够将精力集中在特定的类上,而排除那些不重要的事件,如空闲事件。John对V$SESSION_WAIT_CLASS视图执行下面的查询:

select wait_class_id, wait_class, total_waits, time_waited from v$session_wait_class where sid = 270;

    输出结果它显示出等待类,以及在每个类中会话等待事件的次数。它告诉John,自实例启动后与该应用程序相关的等待,如那些由于行级锁引起的等待出现了17760次,所花费的时间总共为281654厘秒(百分之一秒,cs)。John认为对于这个会话,TIME_WAITED的值太高了。他决定在该application(应用程序)等待类中寻找引起这些等待的原因。在V$SYSTEM_EVENT视图中可以获得每种等待的出现次数。他执行下面的查询来确定application等待类(类id 4217450380)中的每种等待:

select event, total_waits, time_waited from v$system_event e, v$event_name n where n.event_id = e.event_id and wait_class_id = 4217450380;

    该结果显示,在application等待类的等待时间中,锁的争用(由事件enq: TX - row lock contention标识)占了大部分。这与John有关系。是不是编写得不好的应用程序有可能直接进入了产品数据库,从而引起这些锁的争用问题?

    但是,作为一名经验丰富的DBA,John没有立即下这个结论。代码清单3中的数据仅仅表明用户经历了2275次与锁争用有关的等待,共计花费280856厘秒。有可能大多数等待只有1到2厘秒,所有等待时间可能仅仅是由一个长的等待引起的,在这种情况下,该应用程序并没有问题。单个长的等待也许是出现了反常现象它扭曲了数据,而并不代表系统的真正工作负载。John如何确定是否是一个单一等待事件扭曲了该数据呢?

    Oracle 10g提供了一种新的视图,V$EVENT_HISTOGRAM,它显示等待时间周期以及会话等待某一特定时间周期的频度。Jone对V$EVENT_HISTOGRAM执行下面的查询语句:

select wait_time_milli bucket, wait_count from v$event_histogram where event = 'enq: TX - row lock contention';

     V$EVENT_HISTOGRAM视图显示等待时间段以及在这期间会话等待某一特定事件--在本例中就是行级锁争用--的次数。例如,会话等待少于1毫秒(ms)的事件共252次,等待大于1毫秒少于16毫秒的事件1次,等等。WAIT_COUNT列值之和为2275,与代码清单3列出的事件enq:TX - row lock contention中显示的值相同。V$EVENT_HISTOGRAM视图显示,大多数等待发生在256毫秒、512毫秒和4096毫秒的事件上,这就充分证明了该应用程序正在经历锁的争用问题,而这个锁的争用问题就是导致Bill的会话速度减慢的原因。如果视图显示等待发生在1毫秒的范围内,那么John就不能这么认为,因为这样短时间的等待似乎是正常的。

0
相关文章