模拟 ORA-3113:通信通道上的文件结尾

Posted

技术标签:

【中文标题】模拟 ORA-3113:通信通道上的文件结尾【英文标题】:Simulate ORA-3113: end-of-file on communication channel 【发布时间】:2012-09-13 18:43:39 【问题描述】:

我有一个 C# Windows IIS 服务器 (Windows Server 2003) 应用程序连接到托管在 Linux 上的 Oracle 数据库(Red Hat 5.3 上的 10gR2)。 Oracle 会间歇性地抛出 ORA-3113: end-of-file on communication channel 错误。这搞砸了 C# 中的 OracleConnection 对象。然后,任何尝试使用 OracleConnection 的新 OracleCommands 都失败,说明连接已关闭。

我已经查看了此错误生成的 Oracle 跟踪文件,并将问题与网络硬件故障隔离开来,并且正在努力修复它。

但是,我需要使我的 C# 代码更健壮,并通过关闭而不使用该连接对象来适当地响应此错误。在 C# 中很容易捕获异常,但我无法在开发环境中重现网络问题以证明我的代码可以正常工作并自行清理。

try

  oracleCommand.ExecuteNonQuery();

catch(OracleException exception)

  if(exception.Code == 3113)
    CloseAndCleanup();

我尝试在表上编写一个 PL/SQL 触发器,当我尝试向表中插入时抛出 ORA-3113。

CREATE OR REPLACE TRIGGER SCHEMA.TABLE
BEFORE DELETE OR INSERT OR UPDATE
ON SCHEMA.TABLE
FOR EACH ROW
DECLARE
  CONNECTION_LOST_CONTACT   EXCEPTION;
  PRAGMA EXCEPTION_INIT (CONNECTION_LOST_CONTACT, -3113);
BEGIN
  RAISE CONNECTION_LOST_CONTACT;
END;

这会引发正确的错误,但不会破坏 C# 中的 OracleConnection 对象。我仍然可以向 OracleConnection 发送命令并且它可以工作。

如何准确模拟 ORA-3113 错误?

【问题讨论】:

您是否尝试过终止您的 Oracle 会话? (或让您的 dba 为您做) 自己(或通过 DBA)终止 Oracle 会话将导致完全终止,不会引发 ORA-3113。 【参考方案1】:

ORA-3113 表示分配给客户端的服务器进程/线程意外死亡或被故意杀死。 您可以通过手动终止服务器进程/线程来产生ORA-3113 错误。杀死会话不会产生该错误。

要重现该错误,您可以采取以下步骤:

1) 确定与您的会话关联的服务器进程/线程

select p.spid  -- process ID
     , s.program  -- your oracle client
  from v$process p
  join v$session s
    on p.addr = s.paddr 

在服务器端

2) 使用orakill (windows) 或kill -9 .. (Linux) 杀死服务器线程/进程

Windows 示例

c:\> orakill ORACLE_SID spid

之后,您将在客户端获得ORA-3113

【讨论】:

【参考方案2】:

您可以从一些 PL-SQL 代码(例如在触发器中)手动抛出该异常。

【讨论】:

在我的问题中,我说我已经尝试创建一个触发器来抛出异常。【参考方案3】:

你可以杀死你的会话。

alter system kill 'sid,serial#' immediate

您可以查询V$SESSION 或V$MYSTAT 并进行计算,但最好使用sys_contextUSERENV 命名空间。

select sys_context('USERENV','SESSIONID') from dual

将为您获取当前会话 ID (sid),然后您可以查询 V$SESSION 以获取 serial#

此过程将终止运行它的会话:

create or replace procedure kill_my_session is

   l_sid v$session.sid%type;
   l_serial v$session.serial#%type;

begin

   select sid, serial#
     into l_sid, l_serial
     from v$session
    where sid = (select sys_context('USERENV','SESSIONID') from dual)
          ;

   execute immediate 'alter system kill session '''|| l_sid  
                       || ',' || l_serial# || ''' immediate';

end;

当然,您总是可以手动完成,这可能更容易。

【讨论】:

如果我自己发出 Kill 命令,Oracle 会干净利落地关闭连接,不会抛出 ORA-3113。 是的,它不会抛出 ORA-3113,但它会启动你,数据库,这几乎相当于同一件事。但是,如果您随后通过数据库链接运行该过程,那么您可能(我不在数据库附近,无法测试,所以不想肯定地说)得到您所追求的错误。【参考方案4】:

我知道最初的问题是针对 Linux 上的 Oracle 系统设置。对于在 Windows 上运行 Oracle 数据库 XE 的其他人来说,有一种简单的方法可以重现这一点。

进入正在运行的服务(在控制面板\系统和安全\管理工具中)并简单地停止名为 OracleServiceXE 的进程。这也会导致 ORA-03113 出现。

【讨论】:

以上是关于模拟 ORA-3113:通信通道上的文件结尾的主要内容,如果未能解决你的问题,请参考以下文章

ORA-03113:通信通道的文件结尾解决

Oracle错误——ORA-03113:通信通道的文件结尾

ORA-03113:通信通道的文件结尾-完美解决方案

Oracle 11.2.0.1的一个Bug,客户端报ORA-03113: 通信通道的文件结尾

ORA-03113:通信通道的文件结尾-完美解决方案

Oracle Collect Over 分析功能