Oracle 更新/插入卡住,DB CPU 100%,并发高,来自客户端的 SQL*Net 等待消息

Posted

技术标签:

【中文标题】Oracle 更新/插入卡住,DB CPU 100%,并发高,来自客户端的 SQL*Net 等待消息【英文标题】:Oracle updates/inserts stuck, DB CPU at 100%, concurrency high, SQL*Net wait message from client 【发布时间】:2012-12-26 17:02:06 【问题描述】:

我们有一个使用瘦 JDBC 驱动程序在 Weblogic 上针对 Oracle 11g DB 运行的 JavaEE 应用程序。 最近我们在生产中发生了一系列事件,其中更新和插入某个表被卡住或花费比正常时间更长的时间,没有明显的原因。 这导致应用程序使用越来越多的数据库连接(通常在连接池中处于空闲状态),数据库 CPU 和并发性猛增(如 OEM 中所见),整个数据库陷入停顿。 在这些事件中,DBA 找不到插入和更新卡住的任何原因(没有数据库锁)。他们确实看到了很多“来自客户端的 SQL*Net 等待消息”事件。

他们的理论是,应用程序(jdbc 客户端)在插入/更新语句期间以某种方式卡住,原因与数据库无关,同时没有确认数据库对这些语句的响应。事实上,应用程序继续发出越来越多的此类语句并占用越来越多的连接,这就是 CPU 和并发性猛增的原因,导致数据库无响应。

我不相信 - 如果所有会话都忙于等待客户端,CPU 怎么会这么高? 我们无法始终如一地重现这些事件,所以我们在这里真的处于黑暗之中......

有没有人看到过这样的事情,或者对这可能是由什么引起的有任何想法和建议?

谢谢

【问题讨论】:

也许正在寻找类似尝试扩展表空间的东西——也许是磁盘空间有问题? Oracle 是否与 WebLogic 在同一台服务器上运行?还是在不同的服务器上? 一百万个理由,从字面上看...我会像@randy 一样专注于操作系统、磁盘/文件系统(你没有使用 ZFS/NAS 是吗?)等,但我会只能胡乱猜测,而且很可能是错的。在发生这种情况时,如果没有对您的盒子的 root 访问权限,我看不到这里的任何人将如何能够有意义地帮助您。当这种事情发生时,我通常会找几个系统管理员和一个 DBA 或 2 个并确保每个人都坐在一起……我们这里没有那种奢侈。你想要什么样的答案? @code:数据库运行在专用服务器上。 @Ben:你当然是对的,问题是 DBA 和系统管理员在发生这种情况时查看了系统(并且发生了好几次),我们仍然没有有意义的回答...我想我只是希望有人能提出一些我们没有想到的建议... 【参考方案1】:

您所描述的是“连接风暴”。配置不当的连接池将通过打开新连接来服务等待请求来“处理”缓慢响应的连接。这些额外的请求给已经承受压力的服务器带来了更大的压力(如果没有压力,初始连接就不会滞后)。这会引发一个响应不佳的循环,从而产生额外的连接,最终杀死服务器。

您可以通过将数据源的最大容量设置为合理的值来避免连接风暴。 “合理”的定义会根据您的服务器的能力而有所不同,但它可能比您想象的要低。最好的建议是将最大容量设置为与初始容量相同的值。

一旦您阻止了连接风暴,您就可以专注于导致初始速度下降的数据库进程。


大量的SQL*Net wait message from client 事件表明客户端正在做某事而没有联系数据库。这就是为什么您的 DBA 认为问题出在应用程序上的原因。

【讨论】:

实际上,我们的连接池配置为在启动时打开所有连接(初始容量 = 最大容量),因此它永远不会在负载下打开更多连接。关于 SQL*Net 等待 - 我仍然不明白它会如何导致高 CPU 并使数据库无响应...... 我也遇到过类似的问题,但是即使在客户端消失后,卡住的连接仍然存在......【参考方案2】:

我遇到了类似的问题,我在此处记录了该问题:Unkillable Oracle session waiting on "SQL*Net message from client" event。就我而言,问题是由CLOB 类型的绑定变量引起的,该变量绑定到CLOBs 似乎在Oracle 中引起严重问题的地方。以下语句产生的行为与您观察到的相同:

CREATE TABLE t (
  v INT, 
  s VARCHAR2(400 CHAR)
);

var v_s varchar2(50)
exec :v_s := 'abc'

MERGE INTO t                      
USING (
  SELECT 
    1 v, 
    CAST(:v_s AS CLOB) s 
  FROM DUAL
) s 
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
  t.v = s.v        
WHEN NOT MATCHED THEN INSERT (v, s) 
VALUES (s.v, s.s);

很可能,除了MERGE 之外的其他语句也会暴露这种行为,从而产生僵尸会话,因为 Oracle 似乎运行了一些无限循环,从而产生了观察到的 CPU 负载。

【讨论】:

以上是关于Oracle 更新/插入卡住,DB CPU 100%,并发高,来自客户端的 SQL*Net 等待消息的主要内容,如果未能解决你的问题,请参考以下文章

oracle 插入100万条数据,更新100万条数据

如何将视频插入 Oracle db

Oracle 存储过程 插入更新结构

使用 SQL Server 从带有 dblink 的 SQL Server 表向 Oracle DB 表插入数据

Oracle Windows/Linux定期清理归档日志

oracle执行了一条for update卡住了,没有提交。之后再执行修改就改不了了