生产上数据库大量的latch free 导致的CPU资源耗尽的问题的解决

中午的时候,我们生产上的某个数据库,cpu一直居高不下

通过如下的sql语句,我们查看当时数据库的等待,争用的情况:

select s.SID,
       s.SERIAL#,
       'kill -9 ' || p.SPID,
       s.MACHINE,
       s.OSUSER,
       s.PROGRAM,
       s.USERNAME,
       s.last_call_et,
       a.SQL_ID,
       s.LOGON_TIME,
       a.SQL_TEXT,
       a.SQL_FULLTEXT,
       w.EVENT,
       a.DISK_READS,
       a.BUFFER_GETS
  from v$process p, v$session s, v$sqlarea a, v$session_wait w
 where p.ADDR = s.PADDR
   and s.SQL_ID = a.sql_id
   and s.sid = w.SID
   and s.STATUS = 'ACTIVE'
 order by s.last_call_et desc;

从event可以看到,是latch 的争用导致的原因

通过如果的sql,查看是什么样的latch

select * from v$session_wait
where event  like 'latch free';
 

P2就是 这个latch的name,通过v$latchname这个视图就可以知道哪个具体的latch

1:45:55 PM SQL> select * from v$latchname where latch#=164;

    LATCH# NAME                                                                   HASH
---------- ---------------------------------------------------------------- ----------
       164 simulator hash latch                                             2233208730

查看latch的历史情况

2:11:59 PM SQL> select name,gets,misses,sleeps from v$latch where sleeps >0 order by sleeps desc;

NAME                                                                   GETS     MISSES     SLEEPS
---------------------------------------------------------------- ---------- ---------- ----------
simulator hash latch                                             4827860212  135426899   10890947
cache buffers chains                                             1619822817 2850976006    4747728
gc element                                                       4660052091   25748270     175073
resmgr:schema config                                               91872524     153968      95708
ges resource hash list                                            174151449    1070556      55459
Real-time plan statistics latch                                    40953155     651496      44527
call allocation                                                     3301878     265908      43501
row cache objects                                                 336300485    4970324      19366

这个simulator hash latch已经是显著的latch部分

eagle在他的网站上有篇文章讲到了关于simulator这个

http://www.eygle.com/archives/2011/11/simulator_lru_latch.html

simulator意为模拟,也就是说当Oracle在内存中进行数据块处理时,实际上还会在预先分配的Buffer中进行相关信息记录,如DBA信息,当数据块被老化之后,下次读取时,如果请求的数据在Simulator内存中存在,则认为继续缓存该数据块是有意义的,通过监控并模拟统计这些操作,并对计算结果加权运算,就可以实现对于内存的调整建议。

在模拟过程中,也是通过Latch来实现的,相关的Latch就有 simulator lru latch 、 simulator hash latch等.

就Buffer Cache而言,如果系统中该类争用严重,则可以考虑关闭db_cache_advice,消除这部分内部操作对于性能的影响。

以下是一个相关BUG,在该Bug中,由于DB_CACHE_ADVICE的开启导致了严重的simulator lru latch的竞争:

Bug 5918642  Heavy latch contention with DB_CACHE_ADVICE on

This note gives a brief overview of bug 5918642.

The content was last updated on: 01-APR-2008

Click here for
details of each of the sections below.

Affects:

Product (Component) Oracle Server (Rdbms)
Range of versions believed to be affected Versions < 11.2
Versions confirmed as being affected
Platforms affected Generic (all / most platforms affected)

Fixed:

This issue is fixed in

Symptoms:

Related To:

Description

High simulator lru latch contention can occur when db_cache_advice is
set to ON if there is a large buffer cache.

Workaround:
  Set db_cache_advice to OFF

当然,这个只是治标不治本的做法,这个是显现的表象的问题,根源的问题还是这个sql语句有问题

当一个数据块读入到sga中时,该块的块头(buffer header)会放置在一个hash bucket的链表(hash chain)中。该内存结构由一系列cache buffers chains子latch保护(又名hash latch或者cbc latch)。对Buffer cache中的块,要select或者update、insert,delete等,都得先获得cache buffers chains子latch,以保证对chain的排他访问。若在过程中发生争用,就会等待latch:cache buffers
chains事件。

产生原因: 1. 低效率的SQL语句(主要体现在逻辑读过高) 在某些环境中,应用程序打开执行相同的低效率SQL语句的多个并发会话,这些SQL语句都设法得到相同的数据集,每次执行都带有高 BUFFER_GETS(逻辑读取)的SQL语句是主要的原因。相反,较小的逻辑读意味着较少的latch get操作,从而减少锁存器争用并改善性能。注意v$sql中BUFFER_GETS/EXECUTIONS大的语句。 2.Hot block 当多个会话重复访问一个或多个由同一个子cache buffers chains锁存器保护的块时,热块就会产生。当多个会话争用cache
buffers chains子锁存器时,就会出现这个等待事件。有时就算调优了SQL,但多个会话同时执行此SQL,那怕只是扫描特定少数块,也是也会出现HOT BLOCK的。

SELECT P935.SEQUENCEID,
       null FA_SEQUENCEID,
       P935.ORDERID,
       P935.ORGORDERID,
       P935.PRODUCTNAME,
       P935.PRODUCTNUM,
       P935.ORDERTIME,
       P935.LASTUPDATETIME,
       P935.ORDERSTATUS,
       P935.MEMO,
       935 orderCode,
       P935.PAYERACCTCODE,
       P935.PAYERACCTTYPE,
       P935.PAYEEACCTCODE PLATACCTCODE,
       P935.PAYEEACCTTYPE PLATACCTTYPE,
       P936.PAYEEACCTCODE,
       P936.PAYEEACCTTYPE,
       EXT935.PAYER_DISPLAYNAME,
       EXT935.PAYER_NAME,
       EXT935.PAYER_IDC,
       EXT935.PAYER_MEMBERTYPE,
       EXT936.PAYER_DISPLAYNAME PLAT_DISPLAYNAME,
       EXT936.SUBMITNAME PLAT_NAME,
       EXT936.PAYER_IDC PLAT_IDC,
       EXT936.PAYER_MEMBERTYPE PLAT_MEMBERTYPE,
       EXT936.PAYEE_DISPLAYNAME,
       EXT936.PAYEE_NAME,
       EXT936.PAYEE_IDC,
       EXT936.PAYEE_MEMBERTYPE,
       P935.PAYEEDISPLAYNAME WEBSITENAME,
       CASE
         WHEN (SELECT count(*)
                 FROM PAYMENTORDER P936
                WHERE P936.Ordercode = 936
                  and P936.Orderstatus = 0
                  AND <span style="color:#ff0000;">P936.Relatedsequenceid = P935.SEQUENCEID</span>) > 0 THEN
          0
         ELSE
          1
       END AS SHARINGRESULT,
       CASE D935.Dealcode
         WHEN 210 then
          14
         else
          D935.DEALTYPE
       end PAYMETHOD,
       D935.DEALAMOUNT,
       G935.EXT1,
       G935.Ext2,
       G935.PAYERCONTACTTYPE,
       G935.PAYERCONTACT,
       NVL(D935.PAYEEFEE, 0) PAYEEFEE,
       NVL(D935.PAYERFEE, 0) PAYERFEE,
       nvl(MS936.PAYEEFEE, 0) PLATFORMFEE,
       P935.VERSION
  FROM PAYMENTORDER          P935,
       PAYMENTORDER          P936,
       DEAL                  D935,
       GATEWAYORDER          G935,
       MSGATEWAYSHARINGORDER MS936,
       PAYMENTORDEREXT       EXT935,
       PAYMENTORDEREXT       EXT936
 WHERE P936.ORDERCODE = 936
   AND P935.ORDERCODE = 935
   AND P936.RELATEDSEQUENCEID = to_char(P935.SEQUENCEID)
   AND P935.SEQUENCEID = G935.SEQUENCEID(+)
   AND P935.SEQUENCEID = D935.ORDERSEQID(+)
   AND P935.SEQUENCEID = EXT935.ORDERSEQID(+)
   AND P936.SEQUENCEID = EXT936.ORDERSEQID(+)
   AND P936.SEQUENCEID = MS936.SEQUENCEID(+)
   AND MS936.SHARINGTYPE = 1
   AND P935.SEQUENCEID = :1
UNION
SELECT P938.SEQUENCEID,
       P935.SEQUENCEID FA_SEQUENCEID,
       P938.ORDERID,
       P938.ORGORDERID,
       P935.PRODUCTNAME,
       P935.PRODUCTNUM,
       P938.ORDERTIME,
       P938.LASTUPDATETIME,
       P938.ORDERSTATUS,
       P938.MEMO,
       938 orderCode,
       P938.PAYERACCTCODE,
       P938.PAYERACCTTYPE,
       P938.PAYEEACCTCODE PLATACCTCODE,
       P938.PAYEEACCTTYPE PLATACCTTYPE,
       P938.PAYEEACCTCODE,
       P938.PAYEEACCTTYPE,
       EXT938.PAYER_DISPLAYNAME,
       EXT938.PAYER_NAME,
       EXT938.PAYER_IDC,
       EXT938.PAYER_MEMBERTYPE,
       EXT938.PAYEE_DISPLAYNAME PLAT_DISPLAYNAME,
       EXT938.SUBMITNAME PLAT_NAME,
       EXT938.PAYEE_IDC PLAT_IDC,
       EXT938.PAYEE_MEMBERTYPE PLAT_MEMBERTYPE,
       EXT938.PAYEE_DISPLAYNAME,
       EXT938.PAYEE_NAME,
       EXT938.PAYEE_IDC,
       EXT938.PAYEE_MEMBERTYPE,
       P935.PAYEEDISPLAYNAME WEBSITENAME,
       null SHARINGRESULT,
       D938.DEALTYPE PAYMETHOD,
       D938.DEALAMOUNT,
       G935.EXT1,
       G935.Ext2,
       G935.PAYERCONTACTTYPE,
       G935.PAYERCONTACT,
       NVL(D938.PAYEEFEE, 0) PAYEEFEE,
       NVL(D938.PAYERFEE, 0) PAYERFEE,
       0 PLATFORMFEE,
       P935.VERSION
  FROM PAYMENTORDER    P935,
       PAYMENTORDER    P938,
       DEAL            D938,
       GATEWAYORDER    G935,
       PAYMENTORDEREXT EXT938
 WHERE P935.ORDERCODE = 935
   AND P938.ORDERCODE = 938
   AND P938.RELATEDSEQUENCEID = to_char(P935.SEQUENCEID)
   AND P935.SEQUENCEID = G935.SEQUENCEID(+)
   AND P938.SEQUENCEID = D938.ORDERSEQID(+)
   AND P938.SEQUENCEID = EXT938.ORDERSEQID(+)
   AND P935.SEQUENCEID = :2

分析上面的sql,上面标红的地方,等号左边是varchar2的数据类型,括号右边是number的数据类型,会导致数据类型的隐式转换,造成极大的性能影响

联系研发,修改了sql语句,问题解决

时间: 2024-08-28 13:08:13

生产上数据库大量的latch free 导致的CPU资源耗尽的问题的解决的相关文章

TIME_WAIT状态的连接过多导致系统端口资源耗尽问题(2)

继上次解决完mysql连接过多,导致的TIME_WAIT进程过多问题之后,最近这个现象再一次出现,并且依然和之前一样严重.只不过这次出现问题的mysql 服务跟上次不一样,上一次主要是mysql master server,而这一次是mysql slave server.所以这意味着,我们上次解决了部分问题,但没有彻底解决,还存在一部分问题.所以这次彻底的把这个问题好好梳理一下. 再次确认一下TIME_WAIT进程的所属服务: sudo netstat -anp | grep TIME_WAIT

RAC环境产生大量ons进程,导致用户进程资源耗尽,用户切换提示Resource temporarily unavailable

基本要素(时间.用户.问题) 用户才实施了LINUX5.8+11.2.0.4的RAC环境,使用一段时间后,当切换的grid用户的时候,提示Resource temporarily unavailable,如下: [[email protected] bin]# su- grid su: cannot set userid: Resource temporarily unavailable 但是我们在切换其他用户如oracle用户的时候,却能够正常切换,并且CRS集群使用正常,客户端的连接和用户的

线上Java程序导致服务器CPU占用率过高的问题排除过程

博文转至:http://www.jianshu.com/p/3667157d63bb,博文更好效果看原版,转本博文的目的就算是个书签吧,需要时候可以定位原文学习 1.故障现象 客服同事反馈平台系统运行缓慢,网页卡顿严重,多次重启系统后问题依然存在,使用top命令查看服务器情况,发现CPU占用率过高. 2.CPU占用过高问题定位 2.1.定位问题进程 使用top命令查看资源占用情况,发现pid为14063的进程占用了大量的CPU资源,CPU占用率高达776.1%,内存占用率也达到了29.8% [[

解决32位plsql客户端连接不64位Oracle11g上数据库

一.解决方案 因为本人安装的是64位的Oracle,plsql 是32位的故连接不上.网上有方法能连接. 1. 文件下载 下载PLSQL_Developer地址 http://pan.baidu.com/share/link?shareid=3768883331&uk=3557941237 下载instantclient-basic-win32-10.2.0.5地址: http://pan.baidu.com/share/link?shareid=3782452820&uk=3557941

程序连不上数据库的总结

连不上mysql时一般有以下四种报错: 1:Can't connect to MySQL server 2:Lost connection to MySQL server 3:Sorry, due to line fault, temporarily unable to browse, we are dealing with. 4:MySQL server has gone away 一:Can't connect to MySQL server 可能的原因: 1,mysql服务端没有启起来 2

MYSQL数据库表排序规则不一致导致联表查询,索引不起作用问题

Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题 表更描述: 将mysql数据库中的worktask表添加ishaspic字段. 具体操作:(1)数据库worktask表新添是否有图片字段ishaspic:新添字段时,报错 [SQL] alter table WorkTask add ishaspic int(10) Null;[Err] 1034 - Incorrect key file for table 'WorkTask'; try to repair it 解决方案:新建

记一次线上Java程序导致服务器CPU占用率过高的问题排除过程

https://blog.csdn.net/u013991521/article/details/52781423 1.故障现象 客服同事反馈平台系统运行缓慢,网页卡顿严重,多次重启系统后问题依然存在,使用top命令查看服务器情况,发现CPU占用率过高. 2.CPU占用过高问题定位 2.1.定位问题进程 使用top命令查看资源占用情况,发现pid为14063的进程占用了大量的CPU资源,CPU占用率高达776.1%,内存占用率也达到了29.8% [ylp@ylp-web-01 ~]$ top t

ORACLE11g下如何利用SQL DEVELOPER连接上数据库?

最近在学习数据库的相关内容,在sqlplus敲了几天命令行窗口后,想尝试一下用sql developer 连接上数据库但一直没有实现.在网上查询了相关资料后现在终于弄好了,就来写下此篇博文与大家分享!接下来给大家分步骤介绍. 1.打开sql developer后配置java.exe路径.这点装过ecilipse的应该都很熟悉了,在此就不细说了.如果不记得自己java环境的安装路径推荐大家可以下载everything这款window下非常好用的文件搜索软件. 2.打开后我们就可以看到这样的界面.

sqlserver2008能连接本地1433端口,但是程序连不上数据库

原来能成功连接数据库,但今天连接数据库的时候,出现了以下问题(用Java做的测试) 它说连不上1433端口,然后我就去sqlserver的配置管理器看,结果如下:(已经启用) 然后有用cmd测试:成功 后来经过多方在网上搜索,找方法,找到问题所在 1.先打开配置管理器 右击打开SQL Server的属性 2将Network Service 改为Local System 然后就能连接上数据库了