Oracle 不再从套接字读取数据

Oracle 不再从套接字读取数据,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,我的程序如下所示: Declare cur_1 Sys_Refcursor; cur_2 Sys_Refcursor; v_1 VARCHAR2(30); v_2 VARCHAR2(30); v_3 VARCHAR2(30); v_4 VARCHAR2(30); Begin OPEN cur_1 f

我的程序如下所示:

Declare 
       cur_1        Sys_Refcursor;
       cur_2        Sys_Refcursor;
       v_1          VARCHAR2(30);
       v_2          VARCHAR2(30);
       v_3          VARCHAR2(30);
       v_4          VARCHAR2(30);
Begin
       OPEN cur_1 for Select * from tab1@dblink1;
       Loop
           Fetch cur_1 into v_1, v_2;
           EXIT WHEN cur_1%NOTFOUND;   
           OPEN cur_2 for Select * from tab2@dblink1 where col1 = v_1 and col2 = v2;
           Loop
               Fetch cur2 into v_3, v_4;
               Exit when cur_2%notfound;    
               INSERT INTO local.tab3 values (v_1,v_2, v_3, v_4);
           END Loop;
           close cur_2;
       End Loop;
       close cur_1; 
END;
insert into local.tab3(col1, col2, col3, col4)
select tab1.col1, tab1.col2, tab2.col1, tab2.col2
from tab1@dblink1 tab1
join tab2@dblink1 tab2
    on tab1.col1 = tab2.col1
    and tab1.col2 = tab2.col2;
abobe过程会编译,但运行时会出现以下错误:

不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
不再需要从套接字读取数据
…(几乎没有更多“从套接字读取的数据”)

IO错误:对等方重置连接:套接字写入错误
进程已退出

有趣的是,当我注释掉整个内部循环时,程序运行时不会出错。所以我知道内部循环有问题(我试着只注释内部循环中的insert语句,但得到了相同的错误)

我的localdb和dblink1数据库的版本相同:

Oracle数据库11g企业版11.2.0.1.0版-64位生产

PL/SQL 11.2.0.1.0版-生产

核心11.2.0.1.0生产

用于64位Windows的TNS:11.2.0.1.0版-生产

NLSRTL版本11.2.0.1.0-生产

排除“无更多数据可从套接字读取”错误的一般建议。 这些错误通常是由另一个严重错误引起的,例如ORA-600错误。问题严重到服务器进程崩溃,甚至无法向客户端发送正确的错误消息。(这些错误的另一个常见原因是SQLNET.EXPIRE\u TIME或其他终止旧会话的进程导致的网络断开。)

查看警报日志以查找原始错误消息

查找文件alert_u[name]。登录此目录:
从v$参数中选择值,其中name='background_dump_dest'

找到特定错误消息和详细信息后,请转到support.oracle.com。使用“ora-600工具”,然后查找ora-600消息后的第一个数字

对于特定类型的ORA-600错误,通常会有一篇或多篇文章。使用准确的版本和平台来缩小可能的bug列表。(但如果文章中的“受影响的版本”是错误的,不要感到惊讶。Oracle声称的“x.y版本中的修复”并不总是正确的。)

这些文章通常会更详细地解释问题是如何发生的,可能的解决方法,以及通常涉及补丁或升级的解决方案

实际上,你很少想解决这些问题。“典型”建议是与Oracle支持部门联系,以验证您是否确实存在相同的问题,获得修补程序,获得许可并关闭环境,然后应用修补程序。然后可能会意识到补丁不起作用。恭喜你,你浪费了很多时间

相反,您通常可以通过对查询或过程进行细微的更改来避免问题。Oracle有很多功能,几乎总是有另一种方法来实现。如果代码看起来有点奇怪,添加一条注释来警告未来的程序员:“这段代码看起来很奇怪,以避免bug X,这应该在版本Y中修复。”

此代码的具体建议 如果这真的是您的整个过程,您应该将其替换为以下内容:

Declare 
       cur_1        Sys_Refcursor;
       cur_2        Sys_Refcursor;
       v_1          VARCHAR2(30);
       v_2          VARCHAR2(30);
       v_3          VARCHAR2(30);
       v_4          VARCHAR2(30);
Begin
       OPEN cur_1 for Select * from tab1@dblink1;
       Loop
           Fetch cur_1 into v_1, v_2;
           EXIT WHEN cur_1%NOTFOUND;   
           OPEN cur_2 for Select * from tab2@dblink1 where col1 = v_1 and col2 = v2;
           Loop
               Fetch cur2 into v_3, v_4;
               Exit when cur_2%notfound;    
               INSERT INTO local.tab3 values (v_1,v_2, v_3, v_4);
           END Loop;
           close cur_2;
       End Loop;
       close cur_1; 
END;
insert into local.tab3(col1, col2, col3, col4)
select tab1.col1, tab1.col2, tab2.col1, tab2.col2
from tab1@dblink1 tab1
join tab2@dblink1 tab2
    on tab1.col1 = tab2.col1
    and tab1.col2 = tab2.col2;

通常,如果可能的话,您应该始终使用SQL进行操作。尤其是如果您可以避免打开许多游标。尤其是如果您可以避免打开远程数据库的多个游标。

正如jonearles所提到的,您应该在一条SQL语句中编写这条语句

如果您坚持使用PL/SQL:您自己做的工作太多了,声明变量、打开游标、循环、分配变量。考虑这个PL/SQL:

begin
  for c1 in (select * from tab1@dblink1)
  loop
    for c2 in (Select * from tab2@dblink1 where col1 = c1.col1 and col2 = c1.col2)
    loop
      insert into local.tab3 values (c1.col1,c1.col2,c2.col1,c2.col2);
    end loop;
  end loop;
end;
/

使用
@dblink1
连接到的数据库中是否存在
Tab2
?是的,它存在…..当我通过sqlplus运行查询时,它返回一个resultset@tbone:在循环中插入local.tab3值(v_1、v_2、v_3、v_4)后添加提交。不工作:(我找到了以下信息,但无法找出错误所在-线程1无法分配新日志,序列478至9月27日11:16:45 2012线程1无法分配新日志,序列479私有链刷新未完成当前日志#3 seq 480 mem#0:C:\..\ORCL\redoo3.log线程1升级到日志序列481(LGWR开关)当前日志#1 seq#481 mem#0:C:\..\ORCL\REDO01.log Thu Sep 27 15:46:13 2012线程1无法分配新日志,序列482私有串刷新未完成当前日志#1 seq#481 mem#0:C:\..\ORCL\REDO01。LOG@acoolguy我不确定这些信息的确切含义,但我认为它们不是问题所在。我有几十条类似的信息在我的日志中。您可能还需要检查远程数据库的日志。我稍微更改了实现,而不是内部cur_2 sys_refcursor,我在一个新的plsql开始-结束块中使用了简单的cursor,现在这个过程可以工作了!!!我仍然不知道以前的实现为什么不能工作,为什么这个实现可以工作…..有趣的f好主意……如果你在任何一个数据库的日志中都找不到错误消息,我猜这是网络错误。当我使用数据库链接进行临时查询时,有时会出现类似的错误,会话长时间打开,一些网络超时会断开连接。但我不知道如何解决这些问题s、 @jonearles:SQLNET.EXPIRE\u TIME设置用于让数据库检测到死连接。其副作用是,数据库将在EXPIRE\u时间后发送一个空数据包,您可以将其用作保持活动状态。但并非所有防火墙都将空数据包视为通信量,并将断开您的连接。