不可终止的 Oracle 会话正在等待“来自客户端的 SQL*Net 消息”事件

2023-12-28

在 Oracle 11gR2 上,我最近遇到了一个非常有趣的情况,涉及阻塞(但空闲!)MERGE挂在 a 上的声明“来自客户端的 SQL*Net 消息”事件,导致后续并发执行MERGE通过以下方式阻止第一个语句的语句“光标:引脚 S 等待 X”事件。在 Oracle Enterprise Manager 中,可以观察到以下情况:

这种情况变得更加严重,因为上述 Session-ID 1204 无法通过以下任一方法终止:

alter system kill session 'sid,serial#';
alter system kill session 'sid,serial#' immediate;

我们的DBA有时能够杀死操作系统进程,但很多时候,整个数据库需要重新启动。幸运的是,到目前为止,仅在测试系统上进行,从未投入生产。

Note:

我知道这可能是一个与这个相当模糊的问题中报告的类似问题:Oracle 更新/插入卡住、DB CPU 为 100%、并发度高、来自客户端的 SQL*Net 等待消息 https://stackoverflow.com/q/14043668/521799。我仍然会再次报告它,因为我有一个清晰的复制路径,我将报告它作为答案。


这似乎是 Oracle 中的一个错误CLOB数据类型用作传递给的值MERGE声明的ON条款。假设这个数据库:

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

使用内联值进行复制

现在,在任何 Oracle 客户端(包括 SQL*Plus、SQL Developer 或 JDBC)中运行以下语句,这有助于非常轻松地重现问题(我使用的是 Oracle 11g XE 11.2.0.2.0):

MERGE INTO t                      
USING (
  SELECT 
    1 v, 
    CAST('abc' 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);

这个例子很愚蠢,而且CLOB因“意外”而被束缚在这里。尽管如此,这样的语句不应在 Oracle 中创建僵尸会话,但它确实存在。我在 SQL*Plus 中运行上述语句 3 次,然后运行这个...

SELECT 
  s.sid,
  s.serial#,
  s.sql_id,
  s.event,
  s.blocking_session,
  q.sql_text
FROM v$session s
JOIN v$sql q
ON s.sql_id = q.sql_id
WHERE s.username = 'TEST'
AND UPPER(TRIM(q.sql_text)) LIKE 'MERGE%';

...我得到:

sid serial# sql_id          event                       blocking_session
9   3       82a2k4sqzy1jq   cursor: pin S wait on X     92
49  89      82a2k4sqzy1jq   cursor: pin S wait on X     92
92  13      82a2k4sqzy1jq   db file sequential read     

请注意报告的事件有何不同(“数据库文件顺序读取”)来自原始事件(“来自客户端的 SQL*Net 消息”),它使用了绑定变量

使用绑定值进行复制

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);

上述语句在 SQL*Plus 中运行也会产生错误:

sid serial# sql_id          event                           blocking_session
8   1       4w9zuxrumumgj   SQL*Net message from client     
90  7       4w9zuxrumumgj   cursor: pin S wait on X         8
94  21      4w9zuxrumumgj   cursor: pin S wait on X         8

PL/SQL 中无法复制

有趣的是,以下 PL/SQL 语句避免了该错误:

DECLARE
  v_s CLOB := 'abc';
BEGIN
  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);
END;
/

我越来越:

          CAST(v_s AS CLOB) s
          *
ERROR at line 8:
ORA-06550: line 8, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected - got CLOB
ORA-06550: line 4, column 7:
PL/SQL: SQL Statement ignored

看起来 PL/SQL 引擎可以保护客户端免受此 SQL 引擎错误的影响。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

不可终止的 Oracle 会话正在等待“来自客户端的 SQL*Net 消息”事件 的相关文章

  • st_intersects 与 st_overlaps

    这两个查询有什么区别 select a gid sum length b the geom from polygons as a roads as b where st intersects a the geom b the geom gr
  • 提高第一个查询的性能

    如果执行以下数据库 postgres 查询 则第二次调用要快得多 我猜第一个查询很慢 因为操作系统 linux 需要从磁盘获取数据 第二个查询受益于文件系统级别和 postgres 中的缓存 有没有一种方法可以优化数据库以快速获得结果fir
  • 如何识别拼写不同的相似单词

    我想从数据库中过滤掉重复的客户名称 一位客户可能有多个同名但拼写差异不大的系统条目 这是一个示例 名为 Brook 的客户可能有 3 个系统条目 有了这个变化 布鲁克 贝尔塔 布鲁克 贝尔塔 比鲁克 贝尔塔 假设我们将此名称放入一个数据库列
  • 解析带下划线的 SQL Server 数字文字

    我想知道它为什么有效以及为什么它不返回错误 SELECT 2015 11 Result 11 2015 第二种情况 SELECT 2 1 a a 2 1 检查元数据 SELECT name system type name FROM sys
  • 从 Getdate() 获取时间

    我想采取Getdate 结果 例如 2011 10 05 11 26 55 000 into 11 26 55 AM 我看过其他地方并发现 Select RIGHT CONVERT VARCHAR GETDATE 100 7 这给了我 11
  • MYSQL从每个类别中随机选择一条记录

    我有一个数据库Items表看起来像这样 id name category int 有几十万条记录 每个item可以是 7 种不同的之一categories 对应于categories table id category 我想要一个从每个类别
  • 循环预定义值

    有没有办法在 oracle 中执行 for every 如下所示 begin for VAR in 1 2 5 loop dbms output put line The value VAR end loop end 我知道你可以这样做 b
  • 如何使用 SQL Server 2008 将行复制到同一个表中

    A 到目前为止我的方式 sqlCommand CommandText INSERT Table1 column1 column2 column3 SELECT column1 column2 column3 FROM Table1 WHER
  • 如何在 SQL Server 中连接

    我的数据库没有特定的列 因此我通过开关在查询中创建了一个列 我需要的是将此列与数据库中的另一列连接起来 select certificateDuration DurationType case when certificateDuratio
  • 通知设置的数据库设计

    用户可以打开或关闭 他的通知设置 帐户 用于通知 例如 更改帐户资料信息 收到新消息等 通知可以通过电子邮件或手机 推送或短信 发送 用户可以只有 1 封电子邮件和多个手机设备 有什么方法可以改进以下数据库设计或者您会采取不同的方式吗 让我
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • DBMS_UTILITY.COMPILE_SCHEMA(schema => '',compile_all => FALSE) 不会编译无效的包体

    的召唤 BEGIN DBMS UTILITY COMPILE SCHEMA schema gt
  • ConcurrentBag 中可能存在内存泄漏吗?

    我一直在研究新的并发集合 特别是 ConcurrentBag 引起了我的注意 由于 ConcurrentBag 在每个单独的线程上内部保存一个本地集 使用它来跟踪项目 这意味着当线程本身超出范围时 ConcurrentBag 仍将在内存中引
  • 如何从 pl/sql 包运行 http Web 服务请求

    我开发了一个新的程序来调用 Web 服务 但当我运行它时 它显示 Oracle 适配器错误 您能指导我如何解决此错误吗 下面的代码有问题吗 Formatted on 17 07 2014 16 49 02 QP5 v5 185 11230
  • Oracle 中仅在一列上不同

    我想在下表中使用不同的值 但仅在 PlayerID 列上使用 这就是我现在所拥有的 MATCHID PLAYERID TEAMID MATCHDATE STARTDATE 20 5 2 14 JAN 12 01 JUN 11 20 5 4
  • 如何获取日期时间字段的 UTC?

    我正在使用 MySQL 5 并且正在尝试将日期时间字段转换为 UTC TIMESTAMP 这是我所拥有的 但它不起作用 并且不确定我是否可以做到这一点 但有人可以告诉我我做错了什么吗 谢谢 我已经尝试过这个 SELECT UTC TIMES
  • 查询和扫描多行性能缓慢

    下面的查询一行的执行时间为 6 18 分钟 Exception type 1 的基数值为 3 我不知道如何提高性能 Query select count 1 as rage tap from summary funnel 1066 s jo
  • 如何从表中选择所有偶数 id?

    我想从 MySQL 数据库的表中选择所有甚至帖子 ID 然后显示它们 我还想获取所有带有奇怪 id 的帖子并将它们显示在其他地方 我想使用 PHP 来完成此操作 因为这是我使用的服务器端语言 或者 我是否必须选择所有帖子 然后使用 Java
  • Web SQL 数据库 + Javascript 循环

    我正在尝试解决这个问题 但我自己似乎无法解决 我正在使用 Web SQL DB 但无法让循环正常使用它 I use for var i 0 i lt numberofArticles 1 i db transaction function
  • MySQL 的 TEXT 类型的 Oracle 等效项

    Oracle 是否有与 MySQL 等效的列类型TEXT type 如果不是 那么通常如何存储较大的文本块 BLOB varchar 32767 如果重要的话 它是通过 PHP 访问 Oracle 10 历史背景是非常受欢迎的 Oracle

随机推荐