oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题

如何诊断和解决CPU高度消耗(100%)的数据库问题

很多时候我们的服务器可能会经历CPU消耗100%的性能问题.
排除系统的异常,这类问题通常都是因为系统中存在性能低下甚至存在错误的SQL语句, 消耗了大量的CPU所致.

本文通过一个案例就如何捕获这样的SQL给出一个通用的方法.

问题描述:系统CPU高度消耗,系统运行缓慢
OS:Sun Solaris8
Oracle:Oracle9203

1.首先通过Top命令查看

$ top

load averages:  1.61,  1.28,  1.25                     HSWAPJSDB             10:50:44
172 processes: 160 sleeping, 1 running, 3 zombie, 6 stopped, 2 on cpu
CPU states:     % idle,     % user,     % kernel,     % iowait,     % swap
Memory: 4.0G real, 1.4G free, 1.9G swap in use, 8.9G swap free

   PID USERNAME THR PR NCE  SIZE   RES STATE   TIME FLTS    CPU COMMAND
 20521 oracle     1 40   0  1.8G  1.7G run     6:37    0 47.77% oracle
 20845 oracle     1 40   0  1.8G  1.7G cpu02   0:41    0 40.98% oracle
 20847 oracle     1 58   0  1.8G  1.7G sleep   0:00    0  0.84% oracle
 20780 oracle     1 48   0  1.8G  1.7G sleep   0:02    0  0.83% oracle
 15828 oracle     1 58   0  1.8G  1.7G sleep   0:58    0  0.53% oracle
 20867 root       1 58   0 4384K 2560K sleep   0:00    0  0.29% sshd2
 20493 oracle     1 58   0  1.8G  1.7G sleep   0:03    0  0.29% oracle
 20887 oracle     1 48   0  1.8G  1.7G sleep   0:00    0  0.13% oracle
 20851 oracle     1 58   0  1.8G  1.7G sleep   0:00    0  0.10% oracle
 20483 oracle     1 48   0  1.8G  1.7G sleep   0:00    0  0.09% oracle
 20875 oracle     1 45   0 1064K  896K sleep   0:00    0  0.07% sh
 20794 oracle     1 58   0  1.8G  1.7G sleep   0:00    0  0.06% oracle
 20842 jiankong   1 52   2 1224K  896K sleep   0:00    0  0.05% sadc
 20888 oracle     1 55   0 1712K 1272K cpu00   0:00    0  0.05% top
 19954 oracle     1 58   0  1.8G  1.7G sleep  84:25    0  0.04% oracle

                      

我们发现在进城列表里,存在两个高CPU耗用的Oracle进城,分别消耗了47.77%和40.98%的CPU资源.

 

2.找到存在问题的进程信息

 

 
$ ps -ef|grep 20521
  oracle 20909 20875  0 10:50:53 pts/10   0:00 grep 20521
  oracle 20521     1 47 10:43:59 ?        6:45 oraclejshs (LOCAL=NO)
$ ps -ef|grep 20845
  oracle 20845     1 44 10:50:00 ?        0:55 oraclejshs (LOCAL=NO)
  oracle 20918 20875  0 10:50:59 pts/10   0:00 grep 20845

       

确认这是两个远程连接的用户进程.

 

3.熟悉一下我的getsql.sql脚本

 

 
SELECT   /*+ ORDERED */
         sql_text
    FROM v$sqltext a
   WHERE (a.hash_value, a.address) IN (
            SELECT DECODE (sql_hash_value,
                           0, prev_hash_value,
                           sql_hash_value
                          ),
                   DECODE (sql_hash_value, 0, prev_sql_addr, sql_address)
              FROM v$session b
             WHERE b.paddr = (SELECT addr
                                FROM v$process c
                               WHERE c.spid = '&pid'))
ORDER BY piece ASC
/
      

注意这里我们涉及了3个视图,并应用其关联进行数据获取.
首先需要输入一个pid,这个pid即process id,也就是在Top或ps中我们看到的PID.
通过pid和v$process.spid相关联我们可以获得Process的相关信息
进而通过v$process.addr和v$session.paddr相关联,我们就可以获得和session相关的所有信息.
再结合v$sqltext,我们即可获得当前session正在执行的SQL语句.

通过v$process视图,我们得以把操作系统和数据库关联了起来.

 

4.连接数据库,找到问题sql及进程

通过Top中我们观察到的PID,进而应用我的getsql脚本,我们得到以下结果输出.

 

 
$ sqlplus "/ as sysdba"

SQL*Plus: Release 9.2.0.3.0 - Production on Mon Dec 29 10:52:14 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.3.0 - Production

SQL> @getsql
Enter value for spid: 20521
old  10: where c.spid = '&pid'
new  10: where c.spid = '20521'

SQL_TEXT
----------------------------------------------------------------
select * from (select VC2URL,VC2PVDID,VC2MOBILE,VC2ENCRYPTFLAG,S
ERVICEID,VC2SUB_TYPE,CISORDER,NUMGUID,VC2KEY1, VC2NEEDDISORDER,V
C2PACKFLAG,datopertime from hsv_2cpsync where datopertime<=sysda
te and numguid>70000000000308 order by NUMGUid) where rownum<=20

      

那么这段代码就是当前正在疯狂消耗CPU的罪魁祸首.
接下来需要进行的工作就是找出这段代码的问题,看是否可以通过优化提高其效率,减少资源消耗.

 

5.进一步的我们可以通过dbms_system包跟踪该进程

 

SQL> @getsid
Enter value for spid: 20521
old 3: select addr from v$process where spid = &spid)
new 3: select addr from v$process where spid = 20521)

SID SERIAL# USERNAME MACHINE
----------------------------------------------------------------
45 38991 HSUSER_V51 hswapjsptl1.hurray.com.cn

SQL> exec dbms_system.set_sql_trace_in_session(45,38991,true);

PL/SQL procedure successfully completed.

SQL> !

 

这部分内容可以参考:
http://www.eygle.com/case/sql_trace_1.htm

对于Windows上的类似问题,可以参考:
http://www.eygle.com/faq/Use.Nt.tools.manage.Oracle.htm

 

6.一点说明

很多时候,高CPU消耗都是由于问题SQL导致的,所以找到这些SQL通常也就找到了问题所在,通过优化调整
通常就可以解决问题。

但是有时候你可能会发现,这些最消耗CPU的进程是后台进程,这一般是由于异常、BUG或者恢复后的异常
导致的,需要具体问题具体分析了.

Oracle数据库经常会遇到CPU利用率很高的情况

博客分类: 数据库
Oracle SQL Access 企业应用 电信

Oracle数据库经常会遇到CPU利用率很高的情况,这种时候大都是数据库中存在着严重性能低下的SQL语句,这种SQL语句大大的消耗了CPU资源,导致整个系统性能低下。当然,引起严重性能低下的SQL语句的原因是多方面的,具体的原因要具体的来分析,下面通过一个实际的案例来说明如何来诊断和解决CPU利用率高的这类问题。
  操作系统:solairs8
  数据库:Oracle9.2.0.4
  问题描述:现场工程师汇报数据库非常慢,几乎所有应用操作均无法正常进行。
  首先登陆主机,执行top发现CPU资源几乎消耗殆尽,存在很多占用CPU很高的进程,而内存和I/O都不高,具体如下:
  last pid: 26136; load averages: 8.89, 8.91, 8.12
  216 processes: 204 sleeping, 8 running, 4 on cpu
  CPU states: 0.6% idle, 97.3% user, 1.8% kernel, 0.2% iowait, 0.0% swap
  Memory: 8192M real, 1166M free, 14M swap in use, 8179M swap free
  PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND
  25725 oracle 1 50 0 4550M 4508M cpu2 12:23 11.23% oracle
  25774 oracle 1 41 0 4550M 4508M run 14:25 10.66% oracle
  26016 oracle 1 31 0 4550M 4508M run 5:41 10.37% oracle
  26010 oracle 1 41 0 4550M 4508M run 4:40 9.81% oracle
  26014 oracle 1 51 0 4550M 4506M cpu6 4:19 9.76% oracle
  25873 oracle 1 41 0 4550M 4508M run 12:10 9.45% oracle
  25723 oracle 1 50 0 4550M 4508M run 15:09 9.40% oracle
  26121 oracle 1 41 0 4550M 4506M cpu0 1:13 9.28% oracle
  于是先查看数据库的告警日志ALERT文件,并没有发现有什么错误存在,日志显示数据库运行正常,排除数据库本身存在问题。
  然后查看这些占用CPU资源很高的Oracle进程究竟是在做什么操作,使用如下SQL语句:
  select sql_text,spid,v$session.program,process from
  v$sqlarea,v$session,v$process
  where v$sqlarea.address=v$session.sql_address
  and v$sqlarea.hashvalue=v$session.sql_hash_value
  and v$session.paddr=v$process.addr
  and v$process.spid in (PID);
  用top中占用CPU很高的进程的PID替换脚本中的PID,得到相应的Oracle进程所执行的SQL语句,发现占用CPU资源很高的进程都是执行同一个SQL语句:
  SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999
  基本上可以肯定是这个SQL引起了系统CPU资源大量被占用,那究竟是什么原因造成这个SQL这么大量占用CPU资源呢,我们先来看看数据库的进程等待事件都有些什么:
  SQL> select sid,event,p1,p1text from v$session_wait;
   SID EVENT P1 P1TEXT
  ---------- ----------------------------------------------------------------
   12 latch free 4.3982E+12 address
   36 latch free 4.3982E+12 address
   37 latch free 4.3982E+12 address
   84 latch free 4.3982E+12 address
   102 latch free 4.3982E+12 address
   101 latch free 4.3982E+12 address
   85 latch free 4.3982E+12 address
   106 latch free 4.3982E+12 address
   155 latch free 4.3982E+12 address
   151 latch free 4.3982E+12 address
   149 latch free 4.3982E+12 address
   147 latch free 4.3982E+12 address
   1 pmon timer 300 duration
  从上面的查询我们可以看出,大都是latch free的等待事件,然后接着查一下这些latch的等待都是什么进程产生的:
  SQL> select spid from v$process where addr in
  (select paddr from v$session where sid in(84,102,101,106,155,151));
  SPID
  ------------
  25774
  26010
  25873
  25725
  由此看出latch free这个等待事件导致了上面的那个SQL语句都在等待,占用了大量的CPU资源。我们来看看究竟主要是那种类型的latch的等待,根据下面的SQL语句:
  SQL> SELECT latch#, name, gets, misses, sleeps
   FROM v$latch
   WHERE sleeps>0
   ORDER BY sleeps;
  LATCH# NAME GETS MISSES SLEEPS
  ---------- ----------------------------------------------------------------
   15 messages 96876 20 1
   159 library cache pin allocation 407322 43 1
   132 dml lock allocation 194533 213 2
   4 session allocation 304897 48 3
   115 redo allocation 238031 286 4
   17 enqueue hash chains 277510 85 5
   7 session idle bit 2727264 314 16
   158 library cache pin 3881788 5586 58
   156 shared pool 2771629 6184 662
   157 library cache 5637573 25246 801
   98 cache buffers chains 1722750424 758400 109837
  由上面的查询可以看出最主要的latch等待是cache buffers chains,这个latch的等待表明数据库存在单独的BLOCK的竞争这些latch,我们来看这个latch存在的子latch及其对应的类型:
  SQL> SELECT addr, latch#, gets, misses, sleeps
   FROM v$latch_children
   WHERE sleeps>0
   and latch# = 98
   ORDER BY sleeps desc;
  ADDR LATCH# GETS MISSES SLEEPS
  ---------------- ---------- ---------- ---------- ----------
  000004000A3DFD10 98 10840661 82891 389
  000004000A698C70 98 159510 2 244
  0000040009B21738 98 104269771 34926 209
  0000040009B227A8 98 107604659 35697 185
  000004000A3E0D70 98 5447601 18922 156
  000004000A6C2BD0 98 853375 7 134
  0000040009B24888 98 85538409 25752 106
  ……………
  接着我们来查看sleep较多的子latch对应都有哪些对象:
  SQL> select distinct a.owner,a.segment_name,a.segment_type from
   dba_extents a,
  (select dbarfil,dbablk
  from x$bh
  where hladdr in
   (select addr
   from (select addr
   from v$latch_children
   order by sleeps desc)
   where rownum < 5)) b
  where a.RELATIVE_FNO = b.dbarfil
  and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk;
  OWNER SEGMENT_NAME SEGMENT_TYPE
  ---------------------------------------------------------------------------
  TEST I_SERVICE_SERVICESPECID INDEX
  TEST I_SERVICE_SUBSIDIARYID INDEX
  TEST SERVICE TABLE
  TEST MSWITCHDOMAIN TABLE
  TEST I_SERVICE_SC_S INDEX
  …………………
  我们看到在开始的那个SQL语句中的几个对象都有包括在内,于是来看看开始的那个SQL的执行计划:
  SQL> set autotrace trace explain
  SQL>SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999;
  Execution Plan
  ----------------------------------------------------------
   0 SELECT STATEMENT Optimizer=CHOOSE
   1 0 NESTED LOOPS
   2 1 NESTED LOOPS
   3 2 NESTED LOOPS
   4 3 TABLE ACCESS (FULL) OF 'SUBBUREAUNUMBER'
   5 3 TABLE ACCESS (BY INDEX ROWID) OF 'GATEWAYLOC'
   6 5 INDEX (UNIQUE SCAN) OF 'PK_GATEWAYLOC' (UNIQUE)
   7 2 TABLE ACCESS (BY INDEX ROWID) OF 'MSWITCHDOMAIN'
   8 7 INDEX (UNIQUE SCAN) OF 'PK_MSWITCHDOMAIN' (UNIQUE)
   9 1 TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE'
   10 9 AND-EQUAL
   11 10 INDEX (RANGE SCAN) OF 'I_SERVICE_SERVICESPECID' (NON
   -UNIQUE)
   12 10 INDEX (RANGE SCAN) OF 'I_SERVICE_SUBSIDIARYID' (NON-
   UNIQUE)
  根据开始查到的引起latch free等待中的对象和SQL语句的执行计划,觉得SERVICE表上的索引有问题,似乎存在了过多的扫描,于是将同样的SQL语句在别的地市的同样的数据库上执行一下,查看相应的执行计划:
  SQL> set autotrace trace explain
  SQL>SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999;
  Execution Plan
  ----------------------------------------------------------
   0 SELECT STATEMENT Optimizer=CHOOSE
   1 0 TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE'
   2 1 NESTED LOOPS
   3 2 NESTED LOOPS
   4 3 NESTED LOOPS
   5 4 TABLE ACCESS (FULL) OF 'SUBBUREAUNUMBER'
   6 4 TABLE ACCESS (BY INDEX ROWID) OF 'GATEWAYLOC'
   7 6 INDEX (UNIQUE SCAN) OF 'PK_GATEWAYLOC' (UNIQUE)
   8 3 TABLE ACCESS (BY INDEX ROWID) OF 'MSWITCHDOMAIN'
   9 8 INDEX (UNIQUE SCAN) OF 'PK_MSWITCHDOMAIN' (UNIQUE)
   10 2 INDEX (RANGE SCAN) OF 'I_SERVICE_SC_S' (NON-UNIQUE)
  对比两个执行计划,发现索引I_SERVICE_SERVICESPECID和I_SERVICE_SUBSIDIARYID是不应该走的,于是又对比了两个地方SERVICE表上的索引个数:
  SQL> select index_name from user_indexes where table_name='SERVICE';
  INDEX_NAME
  ------------------------------
  I_SERVICE_ACCOUNTNUM
  I_SERVICE_CID
  I_SERVICE_DATEACTIVATED
  I_SERVICE_PRICEPLANID
  I_SERVICE_SC_S
  I_SERVICE_SERVICECODE
  I_SERVICE_SERVICESPECID
  I_SERVICE_SUBSIDIARYID
  PK_SERVICE_SID
  SQL> select index_name from user_indexes where table_name='SERVICE';
  INDEX_NAME
  ------------------------------
  I_SERVICE_ACCOUNTNUM
  I_SERVICE_CID
  I_SERVICE_DATEACTIVATED
  I_SERVICE_SC_S
  I_SERVICE_SERVICECODE
  PK_SERVICE_SID
  发现存在问题的数据库中的SERVICE表上不知道怎么多出了I_SERVICE_PRICEPLANID、I_SERVICE_SERVICESPECID 、I_SERVICE_SUBSIDIARYID三个索引,而这些索引就是导致了开始那个SQL语句用了不该用的索引,引起latch free等待和CPU占用很高的罪魁祸首,于是删除了那三个索引,重新执行相应的SQL语句,很快就得出了结果,CPU的利用率也马上下降为正常了,观察结果如下:
  last pid: 26387; load averages: 1.61, 1.38, 1.21
  195 processes: 194 sleeping, 1 on cpu
  CPU states: 96.2% idle, 1.6% user, 1.7% kernel, 0.5% iowait, 0.0% swap
  Memory: 8192M real, 1183M free, 14M swap in use, 8179M swap free
  PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND
  26383 oracle 1 59 0 4550M 4506M sleep 0:12 4.52% oracle
   409 root 15 59 0 7168K 7008K sleep 173.1H 0.53% picld
  25653 oracle 1 59 0 4550M 4508M sleep 2:12 0.48% oracle
  26384 root 1 59 0 2800K 1912K cpu2 0:00 0.21% top-3.5b8-sun4u
  25569 oracle 1 59 0 4550M 4508M sleep 0:12 0.09% oracle
  25717 oracle 1 59 0 4550M 4507M sleep 0:07 0.05% oracle
  25571 oracle 1 59 0 4550M 4507M sleep 0:10 0.04% oracle
  25681 oracle 1 59 0 4550M 4508M sleep 0:10 0.04% oracle
  25544 oracle 1 58 0 4554M 4501M sleep 0:14 0.03% oracle
  25703 oracle 1 59 0 4550M 4506M sleep 0:23 0.03% oracle
  ………………
  对于CPU利用率过高的情况,如果是SQL语句性能比较低下引起的基本上都可以按照这个思路来诊断和解决问题,当然具体问题还得具体分析,解决问题的方法也有很多种,这里不过是抛砖引玉一下,只要能最终达到我们解决问题的目的就可以了。
  
  
  
  
  
  
  作者简介:
  
  照片
  暂缺
  网名coolyl
  CSDN eMag Oracle电子杂志主编
  现任itpub Oracle管理版版主。
  擅长数据库的维护,对于数据库的安装,调整,备份方面有自己独到的经验。同时也给一些国内的大型企业做过oracle的培训,有一定的培训经验。
  曾做过很多大型项目的数据库维护和支持工作,对oracle的维护有相当多的实际经验,善于现场解决问题。
  曾任职于国内某大型软件企业做oracle数据库的技术支持,客户遍及全国各个行业,尤其是电信,政府行业。
  现任职于某外资电信企业华北区分公司,DBA,负责华北区40多个数据库系统的维护,对大型数据库管理经验丰富。
  《Oracle数据库DBA专题技术精粹》一书的主编及主要作者.

Linux中模拟诊断Oracle高CPU占用

分类: ORACLE_Admin 177人阅读 评论(0) 收藏 举报
 下面是模拟过程
1,在一个session中模拟CPU高使用率,如下:
[sql] view plain copy print ?
  1. declare  
  2. num int:=0;  
  3. begin  
  4. loop  
  5. num:=num+1;  
  6. end loop;  
  7. end;  
  8. /  
2,在shell窗口用top命令查看CPU使用情况: 
[plain] view plain copy print ?
  1. PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND  
  2. 7913 oracle    25   0 24364  23M 22144 R    91.7  2.3   0:44   0 oracle  
3,通过Oracle提供的视图查看Session情况:
[plain] view plain copy print ?
  1. SQL> select addr,spid from v$process where spid='7913';                                                                                                                
  2. ADDR     SPID  
  3. -------- ------------  
  4. 2AA1A6EC 7913  
  5. SQL> select sid,sql_id from v$session where paddr='2AA1A6EC';   
  6.        SID SQL_ID  
  7. ---------- -------------  
  8.        157 948mkp962vqgy  
  9. SQL> select sql_text from v$sql where sql_id='948mkp962vqgy';  
  10. SQL_TEXT  
  11. --------------------------------------------------------------------------------  
  12. declare num int:=0; begin loop num:=num+1; end loop; end;  
4,从上面分析可以知道是执行的SQL有死循环.
将对应的服务进程kill掉 kill -9 7913
[在碰到CPU高占用的时候可以根据上面的步骤,分析对应的session执行的SQL进行不通的处理]

http://blog.csdn.net/kkdelta/article/details/7214731

« 关于 GoogleToolbarNotifier.exe 进程 | Blog首页 | Oracle进程:SMON的功能与作用 »

Oracle10g新进程 MMON 和 MMNL

站内相关文章|Related Articles
MMNL进程与ORA-07445 ktsmg_get_threshold
三言两语 - 关于JOB Queue的文档摘要
MMAN - Oracle 10g的Memory manager进程
关于ocssd进程的三言两语
10g QMON Architecture及AQ_TM_PROCESSES

在Oracle10g中,有两个后台进程是新增的,这里我想说的是MMON和MMNL。

在Oracle不同的文档中,对这两个进程的解释存在歧义。
MMON 应该是 Memory Monitor 的缩写,但是在有的文档中被记录为Manageability Monitor ,这应当是10g早期版本中的称呼,只不过后来发生了变更。
这个进程的主要作用如下:

The memory monitor (MMON) process was introduced in 10g and is associated with the Automatic Workload Repository new features used for automatic problem detection and self-tuning. MMON writes out the required statistics for AWR on a scheduled basis.

另外一个进程是 MMNL ,是 Memory Monitor Light (MMNL) 的缩写,在部分文档中记录为 Manageability Monitor Light .
这个进程的作用如下:

The Memory Monitor Light (MMNL) process is a new process in 10g which works with the Automatic Workload Repository new features (AWR) to write out full statistics buffers to disk as needed.

ORACLE CPU过高的一次调整过程


发现CPU占用率一般都维持在90%以上,由于大量使用FOR UPDATE,造成大量LATCH等等待现象,其中某些多线程SQL又运行非常频繁。很久以前就发现这些问题,给出相对意见,建议不采用FOR UPDATE或在FOR UPDATE上加NOWAIT(见http://spaces.msn.com/sunmoonking/blog/cns!E3BD9CBED01777CA!318.entry   “ELECT FOR UPDATE 相关的知识”一章  ),由于项目进程问题一直没进行程序修改,决定在这次解决掉,以解后顾之忧。
 
调整前要知道如下问题
      1,CPU是多少MHZ
      2,SERVER 端的CPU是否有负荷较重
      3,CLIENT 端的CPU是否有负荷较重
      4,空闲时间(如半夜)CPU使用率是否超过15%,如果超过则需要特别注意了
      5,CPU的PEAK LOAD
      6,CPU的IDLE STATE
 
影响CPU的因素
1,高的无必要的解析会代价昂贵。
     发现那些SQL运行了大量的PARSE
     select sql_text, parse_calls, executions from v$sqlarea order by parse_calls desc;
     SYS的总的PARSE情况
     select name, value from v$sysstat where name = ’parse count%’;
     只有硬解析才能减少,可以绑定变量,或增加每一个SESSION的CACHED CURSORS。
2,导致大量I/O的SQL也会明显占用CPU,如没有INDEX。BUFFER GETS一般会同CPU一块增长。可以通过v$sqlarea发现buffer_gets
3,其他等待时间,可以通过v$sesstat,v$sysstat查看
 
#VMSTAT 5 5 的CPU部分
      us  user用掉的
      sy  system用掉的
      id  空闲
 
调整前
TOPAS
      Name            PID  CPU%  PgSp Owner
      oracle       688416  25.2   4.6 orasbp
      oracle       569658  24.9   4.5 orasbp
      topas        676210   0.1   2.9 root
      syncd         77964   0.0   0.5 root
      hatsd        159792   0.0   8.3 root

或者ps aux|head
检查CPU数量
      /usr/sbin/bindprocessor -q
      The available processors are:  0 1 2 3
 
STATSPACK的信息
                                                     Total Wait   wait    Waits
Event                               Waits   Timeouts   Time (s)   (ms)     /txn
---------------------------- ------------ ---------- ---------- ------ --------
enqueue                             5,465        121      1,793    328      0.6
latch free                          2,986      2,669         21      7      0.3
根据消耗最多CPU的进程PID来得到SID详细信息
select s.sid from v$process p, v$session s
where s.paddr=p.addr and p.spid =  &your_spid;
根据SID查SQL
SELECT SQL_TEXT from V$SQLTEXT_WITH_NEWLINES where HASH_VALUE
= (select sql_hash_value from v$session
where SID = ) ;
还有
select n.name,s.value
from v$statname n,V$sesstat s
where n.statistic# = s.statistic#
and value > 0
and s.sid = (select a.sid from v$process p,v$session a
where p.addr =a.paddr
and a.terminal = userenv(’terminal’))
order by n.class,n.name
用以上SQL完成SHELL(shell信息在后面whoit.sh),运行
sh whoit.sh 688416  来根据PID得到用户信息和SQL语句

在STATSPACK和我的whoit.sh都指定是这个SQL的问题
SELECT demessageid, fromid, apptype, demessage,appversion,vovers
ion ,toid,tag FROM de_receivelog  WHERE (status = :1 and rownum<
=1 and (dealtime is null or dealtime delock=1 and Update_Date update
 
再看等待事件
 select sid||' '||event||' '|| total_waits||' '||average_wait               from v$session_event where sid=25
SQL> /
SID||''||EVENT||''||TOTAL_WAITS||''||AVERAGE_WAIT
--------------------------------------------------------------------------------
25 latch free 46180 1
25 control file sequential read 4 0
25 log file sync 1 0
25 db file sequential read 202 0
25 db file scattered read 445 1
25 SQL*Net message to client 22 0
25 SQL*Net message from client 22 0
 
只有一个DEFAULT 池
NAME                                      HIT_RATIO
---------------------------------------- ----------
DEFAULT                                   .88042806
 
设置db_keep_cache_size池,并KEEP表
ALTER  TABLE customer STORAGE (BUFFER_POOL  RECYCLE|KEEP|DFAULT)

SQL> analyze table sbpopt.de_receivelog compute statistics;
建立相关索引
alter table  TI_REPAIR_DEED storage(buffer_pool keep);
alter table  de_receivelog  storage(buffer_pool keep);

 
看到相关的等待都是LATCH FREE,enqueue,估计是由于SELECT FOR UPDATE并且全表扫描造成的
查看每个Session的CPU利用情况:
select ss.sid||' '||se.command||' '||ss.value CPU ||' '||se.username||' '||se.program
from v$sesstat ss, v$session se
where ss.statistic# in
(select statistic#
from v$statname
where name = 'CPU used by this session')
and se.sid=ss.sid
and ss.sid>6
order by ss.value
 
根据STATSPACK的HASH VALUE 用SQL>@sprepsql得到
STATSPACK SQL report for Hash Value: 1710202187  Module: JDBC Thin Client
DB Name         DB Id    Instance     Inst Num Release     Cluster Host
------------ ----------- ------------ -------- ----------- ------- ------------
SBP           3008872479 SBP                 1 9.2.0.6.0   NO      svodbp01
 Start Id     Start Time         End Id      End Time       Duration(mins)
--------- ------------------- --------- ------------------- --------------
       44 23-May-06 14:13:01         45 23-May-06 14:28:00           14.98
SQL Statistics
~~~~~~~~~~~~~~
-> CPU and Elapsed Time are in seconds (s) for Statement Total and in
   milliseconds (ms) for Per Execute
                                                       % Snap
                     Statement Total      Per Execute   Total
                     ---------------  ---------------  ------
        Buffer Gets:       6,938,821          7,608.4   63.34
         Disk Reads:               0              0.0     .00
     Rows processed:             197              0.2
     CPU Time(s/ms):             508            557.2
 Elapsed Time(s/ms):             607            665.8
              Sorts:           1,292              1.4
        Parse Calls:             191               .2
      Invalidations:               0
      Version count:               1
    Sharable Mem(K):              22
         Executions:             912
SQL Text
~~~~~~~~
SELECT demessageid, fromid, apptype, demessage,appversion,vovers
ion ,toid,tag FROM de_receivelog  WHERE (status = :1 and rownum<
=1 and (dealtime is null or dealtime delock=1 and Update_Date update nowait
===============================================================
15分钟内执行了912次,占用22K内存(不多),每次执行1.4个排序,共花了508秒,由于已经采取措施将此表KEEP与内存中,因此没有磁盘读,但每次的逻辑读7,608.4个块

文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/7_databases/oracle/Oracleshl/2008810/135671.html


 

 

 

星期一, 十月 11, 2004

使用Windows工具管理Nt上的Oracle数据库

原文链接:

http://www.eygle.com/faq/Use.Nt.tools.manage.Oracle.htm

1.TOP

Top 工具可以监视最消耗系统资源的进程

Pid 即process id,Windows是多线程服务器,每个进程包含一系列线程,这个与UNIX不同,Unix每个Oralce进程独立存在,在Nt上所有线程由Oralce进程衍生。

所以只用TOP工具我们还无法找出每个连接的用户进程。

 

71% 00000000?1?16384?0?8:52:53.936 No Name Found0% 00000008?4116?282624?24576?0:00:45.164 System1% 000000B8?27023?991232 2207744?0:03:10.313 CSRSS.EXE0% 00000524?1844 2035712 3137536?0:00:11.726 rundll32.exe0% 0000032C?1002 1765376 1380352?0:00:08.432 AOM.exe0% 000004E8?773695 7610368 8146944?0:04:26.533 XDICT.EXE0% 00000720?583880 5079040 33280000?0:08:29.122 NetCaptor.exe23% 000006F4?11882 37056512 79757312?0:00:07.661 oracle.exe0% 00000420?1622 1478656 2420736?0:00:00.170 SQLPLUS.EXE                      

如果windows上由于某个进程的sql或其他问题导致资源过度占用或消耗,比如如下这样一条语句,那么我们怎样来找到这条问题sql呢?

oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题_第1张图片

2.QSLICE

找到最消耗资源的线程号,本例中为(6ec),为16进制,需要转换,v$process视图中的进程ID为十进制

oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题_第2张图片

使用getsql.sql脚本即可获得当前正在执行的SQL语句:

 

REM getsql.sqlREM author eygleREM 在windows上,已知进程ID,得到当前正在执行的语句REM 在windows上,进程ID为16进制,需要转换,在UNIX直接为10进制SELECT   /*+ ORDERED */         sql_text    FROM v$sqltext a   WHERE (a.hash_value, a.address) IN (            SELECT DECODE (sql_hash_value,                           0, prev_hash_value,                           sql_hash_value                          ),                   DECODE (sql_hash_value, 0, prev_sql_addr, sql_address)              FROM v$session b             WHERE b.paddr = (SELECT addr                                FROM v$process c                               WHERE c.spid = TO_NUMBER ('&pid', 'xxxx')))ORDER BY piece ASC/

运行以上脚本:

oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题_第3张图片

 

ok,找到这最消耗资源的问题SQL接下来就可以进行针对性调整了.

相关工具下载地址:

http://www.microsoft.com/windows2000/techinfo/reskit/tools/existing/qslice-o.asp

 

oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题_第4张图片


http://blog.itpub.net/post/7/2958

1:检查系统

  sar -u 5 5

  2: 看谁在用CPU

  topas

  ps -ef |grep ora #检查第四列,C的大小(unit,100 per cpu)

  3:检查CPU数量

  /usr/sbin/bindprocessor -q

  lsattr El proc0

  4:两种可能:

  1: A Background (instance) process

  2: An oracle (user) process #此种可能最大。

  5: 如果是用户进程:那么高CPU的主要原因有:

  Large Queries, Procedure compilation or execution,

  Space management and Sorting

  5.1 查看每个Session的CPU利用情况:

  select ss.sid,se.command,ss.value CPU ,se.username,se.program

  from v$sesstat ss, v$session se

  where ss.statistic# in

  (select statistic#

  from v$statname

  where name = 'CPU used by this session')

  and se.sid=ss.sid

  and ss.sid>6

  order by ss.sid

  5.2: 比较上述Session

  比较一下哪个session的CPU使用时间最多,然后查看该Session的具体情况:

  select s.sid, event, wait_time, w.seq#, q.sql_text

  from v$session_wait w, v$session s, v$process p, v$sqlarea q

  where s.paddr=p.addr and

  s.sid=&p and

  s.sql_address=q.address;

  5.3:查看

  得到上述信息后,查看相应操作是否有hash joins 和 full table scans。如果有hash joins 和 full table scans那么必须创建相应的Index或者检查Index是否有效。

  另外必须检查是否有并行的查询存在和同一时刻有多个用户在执行相同的SQL语句,如果有必须关闭并行的查询和任何类型的并行提示(hints);如果查询使用intermedia数据,那么为了减少总的Index大小,必须限制使用Intermedia的Worldlist。(try restricting the wordlist that intermedia uses to help reduce the total indexsize)。

  6:注意事项

  上述方案只能根据已经运行完成的操作,对于正在执行的长时间操作只能等操作完成后才能检测得到。因此我们可以通过另外一个很好的工具来检测正在运行的长时间操作语句。v$session_longops,这个视图显示那些操作正在被运行,或者已经完成。每个process完成后会刷新本视图的信息。

  7:怎样寻找集中使用CPU的Process

  很多时候会发现有N个Process在平均分享着CPU的利用率,这种情况唯一的可能性就是这些Process在执行着相同的Package或者Query.

  这种情况:建议通过statspack,在CPU高利用率额时候运行几个快照,然后根据这些快照检查Statspack报告,检查报告中最TOP的Query。然后使用 sql_trace and tkprof 工具去跟踪一下。

  同时检查buffer cache 的命中率是否大雨95%。

  同时在报告中还需要检查一下table scans (long tables),看是否在报告生成期间有存在全表扫描。

  8:参数

  另外还有一些不是特别重要的,但是也必须关心检查的参数可能消耗CPU。

  parallel query 并行查询:

  并行查询最好用于数据仓库的环境下,那种情况任何时候只有几个用户在同时使用。在一个联机事务处理环境中,当同时许多用户去并行查询一个数据库的巨大表时候,会导致CPU的爆满。所以最好在数据库的级别关闭并行查询:设置参数如下:

  parallel_min_server = 0  parallel_max_server = 0

  parallel_automatic_tuning = false;

  在配置上述参数后,如果SQL语句中使用的并行的提示,那么还是有可能会出现并行查询的情况,所以还需要继续监视相关的SQL语句,如果有可以直接去除提示。

以前一直想整理一下关于Oracle 的等待事件,总是没时间。现在觉得应该着手做了,其中的一些知识来自于自己的一点研究,如有错误,望大家指正。。。。。

一 Oracle等待事件主要有两类事件:

1 空闲等待

 空闲等待意味着Oracle正在等待某种动作的发生,实际上并不是因为繁忙而等待,而是因为没有事情做所以等待,如:smon timer,SMON进程的一些操作时每隔一段实际循环执行的,即使系统不忙,此事件也不立即发生,而是等待计时器达到一定的时间才执行,此时出现的smon timer 等待事件,而系统并没有出现性能上的问题。多数的空闲等待对数据库性能的影响不大,可以不必过多的关注。

空闲等待事件有:(加注释的比较典型)

      1 dispatcher timer  调度器计时器

      2 lock element cleanup

  3 Null event  null事件

 4  parallel query dequeue wait

  5  parallel query idle wait - Slaves

  6 pipe get 管道取操作

  7  PL/SQL lock timer

  8 pmon timer- pmon

  9  rdbms ipc message  数据库ipc 消息

  10 slave wait

  11  smon timer    smon 计时器

  12 SQL*Net break/reset to client

  13 SQL*Net message from client  来自客户端的消息

  14  SQL*Net message to client  发送消息到客户端

  15 SQL*Net more data to client

  16 virtual circuit status 虚拟环路状态消息

  17 client message  客户机消息

2 非空闲等待事件:

        通常数据库发生竞争时就会出现非空闲的等待事件,即某种操作A发生时,A所需要的资源正在被其他的操作占用,而这种独占的资源不能被操作A请求立即得到,操作请求被堵塞而发生等待。这些等待事件是我们在调整数据库的时候应该关注与研究的。非空闲的等待主要有:

Buffer busy wait    :    表示在等待对数据告诉缓存区的访问,这种等待出现在会话读取数据到buffer中或者修改buffer中的数据时。

Db file parrle write        于dbwr进程相关的等待,一般都代表了io能力出现问题。通常与配置的多个dbwr进程或者dbwr的io slaves个数有关,当然也可能意味这在设备上出现io竞争!
Db file scattered read        表示发生了于全表扫描的等待。通常意味者全表扫描过多,或者io能力不足,或者io竞争。
Db file sequential read        表示发生了于索引扫描有关的等待。

Db file single write        表示在检查点发生时与文件头写操作相关的等待。

Direct path read        表示于直接io读相关的等待。

Direct path write        同上
Enqueue        表示于内部队列机制有关的等待,例如保护内部资源或者组件的锁的请求等,一种并发的保护机制。
Free buffer inspected        表示在将数据读入数据告诉缓冲区的时候等待进程找到足够大的内存空间。

Free buffer waits        表述数据告诉缓存区缺少内存空间。通常于数据高速缓冲区内存太小或者脏数据写出太慢导致。

Latch free       表示某个锁存器发生了竞争。

Library cache load lock        表示在将对象装入到库高速缓冲区的时候出现了等待。这种事件通常代表者发生了负荷很重的语句重载或者装载,可能由于sql语句没有共享池区域偏小导致的。
Library cache lock        表示与访问库高速缓存的多个进程相关的等待。通常表示不合理的共享池大小。
Library cache pin        这个等待事件也与库高速缓存的并发性有关,当库高速缓存中的对象被修改或者被检测的时候发生
Log buffer space        表示日志缓冲区出现了空间等待事件。这种等待事件意味者写日志缓冲区的时候得不到相应的内存空间,通常发生在日志缓冲区太小或者LGWR进程写太慢的时候。
Log file parallel write        表示等待LGWR向操作系统请求io开始直到完成io。在触发LGWR写的情况下入3秒,1/3,1MB、DBWR写之前可能发生。这种事件发生通常表示日志文件发生了io竞争或者文件所在的驱动器较慢。
Log file single write        表示写文件头块的时候出现了等待。一般都是发生在检查点发生时。
Log file switch  (archiveing needed)        由于归档过慢造成日志无法进行切换而发生的等待。这种等待事件的原因可能比较多,最主要的原因是归档速度赶不上日志切换的速度。可能的原因包括了重作日志太了,重作日志组太少,归档能力低,归档文件发生了io竞争,归档日志挂起,或者归档日志放在了慢的设备上。
Log file switch (checkpoint incomplete)        表示在日志切换的时候文件上的检查点还没有完成。一般意味者日志文件太小造成日志切换切换太快或者其他原因。
Log file sync        表示当服务进程发出commit或者rollbabk命令后,直到LGWR完成相关日志写操作这段时间的等待。如果有多个服务进程同时发出这种命令,LGWR不能及时完成日志的写操作,就有可能造成这种等待。
Transaction        表示发生一个阻赛回滚操作的等待。
Undo segment extension        表示在等待回滚段的动态扩展。这表示可能事务量过大,同时也意味者可能回滚段的初始大小不是最优,minextents设置偏小。考虑减少事务,或者使用最小区数更多的回滚段。

参考:

《Oracle 数据性能优化》

SQL*Net message from client 事件产生的原因分析
今天同事运行一个程序,修改表的内容,但运行一半总是挂起,查询数据库看有什么在等待,
查询v$session_wait
SELECT S.SID,
       S.SERIAL#,
       S.USERNAME,
       S.STATUS,
       S.MACHINE,
       S.PROGRAM,
       S.MODULE,
       A.SQL_TEXT
  FROM V$SESSION S,
       V$SQLAREA A
WHERE S.USERNAME IS NOT NULL
   AND S.SQL_ADDRESS = A.ADDRESS
看见同事那个会话在那挂起,看见 SQL* Net message from client 等待时间最长,其实这个是oracle空闲等待时间,只要网络没有问题,可以不用考略这个wait。后来同事修改了下程序通过了,他是因为执行了大查询,而无反应。
下面是参考文档:
1.对于一个session来说,每时每刻都在wait 的状态。
WAIT FOR IO / WAIT FOR CPU / WAIT FOR LATCH /WAIT FOR ...
这一点你可以Query v$session_wait,总有data.

2.对于Server process来说,但它处理完所有需要处理的东西之后,它就进入另一个WAIT, SQL* Net message from client ,等待着Cilent发来信息让它处理,而我们把这种wait叫做 ildel event,并不代表真正的loading

3.举一个例子,你在工作,比如说1:00-1:30在检查DB状态,1:30 - 2:00在读文档。但是,有时候你没什么事做,这时候老板问你在干吗,你就会说,我在等待任务呢,实际上是在休息, 就相当于你wait for " 任务from老板“,事实上是在休息,也就是没有loading.

4.当然也有其他情况,比如,你在座位上休息 (wait for "任务 from老板“ ) ,本来应该是idle的。但是过一会,你老板跑来,暴跳如雷:“我刚才想叫你出去买咖啡,怎么打了半天电话也没人接“,你一查,原来是分机没接好。这种情况下的 (wait for "任务 from老板“ ) 就不正常了。相 对应的Oracle里的就是网络不畅,Client想发信息给Server process,结果不成功,而Server process一直是wait for SQL*Net message from client .

5.结论, 只要网络没问题。SQL*Net message from client 这个wait不用管。http://blog.csdn.net/wyzxg/article/details/1954307

Hits per Second 的真正含义
上一篇 / 下一篇  2008-01-30 12:19:05 / 个人分类:旧资料

查看( 643 ) / 评论( 0 ) / 评分( 0 / 0 )
copy from : http://hi.baidu.com/insight/blog/item/3c452f73735c1f1f8601b051.html
每一个Hit 对应与HTTP服务器访问日志中的每一个HTTP请求。
172.168.1.111 - - [08/Nov/2007:14:37:21 +0800] "GET / HTTP/1.1" 200 0 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)"

172.168.1.111 - - [08/Nov/2007:14:42:24 +0800] "GET /images/shouye/left_01.jpg HTTP/1.1" 304 - "http://172.168.1.6:82/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322)"


上面就是2个Hit。

附:HTTP请求的几个常用类型

HTTP method
 Descrīption
 
GET
 Send named resource from the server to the client.

(从服务器上发送给客户端指定的资源)
 
PUT
 Store data from client into a named server resource.

(从客户端存储数据到一个指定的服务器资源)
 
DELETE
 Delete the named resource from a server.

(从服务器上删除指定的资源)
 
POST
 Send client data into a server gateway application.

(发送客户端数据给服务器上的gateway应用)
 
HEAD
 Send just the HTTP headers from the response for the named resource.

(对于指定的资源只发送HTTP header响应信息,即不传输主体数据
 

http://www.51testing.com/?uid-127689-action-viewspace-itemid-73622

tomcat6可以支持apr以此来提高tomcat处理静态页面的能力。

http://www.diybl.com/course/6_system/linux/Linuxjs/2008622/127482.html

http://lin128.blog.51cto.com/407924/276977

你可能感兴趣的:(oracle CPU使用太高 如何诊断和解决CPU高度消耗(100%)的数据库问题)