当前位置:首页 > 问答 > 正文

Oracle数据库负载怎么查?分享几个实用又简单的查询小技巧,帮你快速定位问题

想知道你的Oracle数据库现在是不是“累坏了”,不用急着找那些特别复杂的专业工具,用数据库自带的SQL语句就能看出很多门道,下面这几个方法,是很多有经验的工程师经常用的,很简单,但能快速帮你判断问题出在哪儿。

第一招:看看谁在“占着茅坑不拉屎”

数据库慢,很多时候是因为有某些会话(可以理解成一个用户连接)长时间占着关键资源不放,导致其他会话排队等着,这时候,你需要找出这些“捣蛋鬼”。

你可以运行下面这个查询(来源:基于V$SESSIONV$SQL视图的常见用法):

SELECT s.sid, s.serial#, s.username, s.program, s.machine, s.last_call_et,
       sq.sql_text, s.blocking_session, s.event
FROM v$session s
LEFT JOIN v$sql sq ON s.sql_id = sq.sql_id
WHERE s.status = 'ACTIVE'
AND s.type <> 'BACKGROUND'
AND s.last_call_et > 60 -- 找出活跃时间超过60秒的会话
ORDER BY s.last_call_et DESC;

这个查询能告诉你:

  • sid, serial#:这是会话的唯一身份证,如果你发现某个会话有问题,可以用ALTER SYSTEM KILL SESSION 'sid,serial#';来干掉它。
  • username, program, machine:是谁、用什么程序、从哪台电脑连过来的,如果是某个特定程序或用户一直活跃,问题可能就出在它身上。
  • last_call_et:这个会话最后一次执行操作已经过了多少秒,数值很大说明它可能卡住了。
  • sql_text:它正在执行什么SQL语句,这条SQL可能就是罪魁祸首。
  • blocking_session:如果这个会话正在阻塞别的会话,这里会显示它被谁阻塞,这是找锁冲突的关键。
  • event:会话当前在等待什么事件,比如等一个文件读写,或者等一个锁。

第二招:数据库整体忙不忙?看这几个数字

如果你想看数据库过去一段时间的整体表现,而不是当前瞬间的状态,V$SYSMETRIC视图是你的好朋友(来源:Oracle官方动态性能视图)。

SELECT metric_name, value, metric_unit
FROM v$sysmetric
WHERE metric_name IN ('Database CPU Time Ratio',
                     'Database Wait Time Ratio',
                     'Average Active Sessions',
                     'SQL Service Response Time')
AND group_id = 2; -- group_id=2 通常表示最近一分钟的指标

这几个指标非常直观:

  • Database CPU Time Ratio:数据库花在CPU运算上的时间比例,如果这个值持续很低(比如低于90%),说明CPU不是瓶颈,时间都花在等待(比如IO)上了。
  • Database Wait Time Ratio:反过来,花在等待上的时间比例,这个值高就需要用下一招去深挖等的是什么。
  • Average Active Sessions (AAS):平均有多少个会话在同时活跃地干活,这个数如果持续超过你CPU的核心数,数据库肯定就忙不过来了。
  • SQL Service Response Time:执行SQL的平均响应时间,突然变长肯定有问题。

第三招:大家到底在“等”什么?

如果上面发现Wait Time Ratio很高,那你一定要用这招,数据库的等待事件就像医院的“分诊台”,告诉你大家抱怨最多的问题是什么(来源:Oracle等待事件分析的核心思想)。

SELECT event, total_waits, time_waited_micro, average_wait_micro
FROM v$system_event
WHERE wait_class <> 'Idle' -- 过滤掉空闲等待事件,#39;SQL*Net message from client'
ORDER BY time_waited_micro DESC;

常见的等待事件和它们的含义:

  • db file sequential read:通常是索引读取或通过ROWID访问单块数据,如果这个等待很突出,可能SQL语句需要优化(比如加索引),或者磁盘读速度太慢。
  • db file scattered read:通常是全表扫描多块数据,如果这个等待很多,说明可能有很多大表扫描,需要考虑SQL写法或索引。
  • log file sync:当用户提交事务时发生,如果这个等待时间长,可能说明日志文件写入慢(比如磁盘IO瓶颈),或者提交太频繁。
  • enq: TX - row lock contention:这就是经典的行锁等待,说明有会话在等别的会话释放某行数据的锁,可能是应用程序逻辑有问题,导致锁没及时释放。

第四招:是不是有SQL语句在“搞破坏”?

很多时候,数据库的负载就是由几条写得烂的SQL语句引起的,找出这些高负载的SQL(来源:基于V$SQLAREA的常见性能查询)。

SELECT sql_id, executions, elapsed_time, cpu_time, disk_reads, buffer_gets, sql_text
FROM v$sqlarea
ORDER BY elapsed_time DESC;

看结果的时候,重点关注:

  • elapsed_time/cpu_time:总耗时和CPU耗时,如果两者都高,说明SQL本身计算复杂。
  • disk_reads:物理读磁盘次数,这个值高意味着SQL需要从硬盘读大量数据,非常慢,理想情况是数据都在内存(buffer_gets)里。
  • buffer_gets:逻辑读次数,即使都在内存里,如果这个值异常高,说明SQL可能没走对索引,扫描了太多数据块。
  • elapsed_time除以executions(执行次数)得到平均每次执行时间,找那些执行次数不一定多,但每次执行都特别耗时的SQL,它们对单次用户体验伤害最大;也要找那些执行次数巨大,虽然单次快,但累积起来拖垮系统的SQL。

把这几个小技巧结合起来用,你就能快速给数据库“体检”了:

  1. 先用第二招看整体指标,判断CPU忙还是等待忙。
  2. 如果等待忙,用第三招看大家在等什么。
  3. 同时用第一招看看有没有异常会话卡住。
  4. 最后用第四招揪出最消耗资源的SQL语句。

这些方法不需要你懂很深奥的原理,上手就能用,能解决大部分常见的负载高、响应慢的问题,如果问题非常复杂,还需要更深入的工具和分析,但这几步已经能帮你定位绝大多数情况了。

Oracle数据库负载怎么查?分享几个实用又简单的查询小技巧,帮你快速定位问题