Oracle11g:JDBC作业中止,并带有;IO错误:连接重置“;

Oracle11g:JDBC作业中止,并带有;IO错误:连接重置“;,oracle,jdbc,Oracle,Jdbc,我正试图弄明白为什么我们的甲骨文11g一直行为不端。在使用JDBC访问数据库的所有作业中,我们都遇到以下错误: Error message: java.sql.SQLRecoverableException: IO Error: Connection reset 在任何人感到不安之前,是的,我已经检查了stack overflow上的其他相关链接(天知道还有多少其他站点)。到目前为止,一切都无济于事,我想知道下一步我能做些什么 在过去几个月里,情况恶化了,唯一改变的是访问数据库的作业在dock

我正试图弄明白为什么我们的甲骨文11g一直行为不端。在使用JDBC访问数据库的所有作业中,我们都遇到以下错误:

Error message: java.sql.SQLRecoverableException: IO Error: Connection reset
在任何人感到不安之前,是的,我已经检查了stack overflow上的其他相关链接(天知道还有多少其他站点)。到目前为止,一切都无济于事,我想知道下一步我能做些什么

在过去几个月里,情况恶化了,唯一改变的是访问数据库的作业在docker容器中运行。唯一受影响的数据库是oracle 11g(我们还有其他几个数据库,包括oracle 12c)。我可以使用sqlplus轻松访问11g数据库

由于这是一个连接问题,我自然检查了文件
tnsnames.ora
listener.ora
。下面是它们包含的内容(所讨论的数据库是SID=TMF)。 tnsnames.ora:

GLOB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = GLOB)
    )
  )

STATIC =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = STATIC)
    )
  )

TMF =
  (DESCRIPTION =
    (SDU=2048)
    (TDU=2048)
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = SHARED)
      (SERVICE_NAME = TMF)
    )
  )

DEMO =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = DEMO)
    )
  )

HONDADB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = HONDADB)
    )
  )

TEMP =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = TEMP)
    )
  )

EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )
listener.ora:

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = TMF)
      (ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
      (SID_NAME = TMF)
    )

    (SID_DESC =
      (GLOBAL_DBNAME = STATIC)
      (ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
      (SID_NAME = STATIC)
    )

    (SID_DESC =
      (GLOBAL_DBNAME = DEMO)
      (ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
      (SID_NAME = DEMO)
    )
  )


LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )
我看不出有什么不对。侦听器跟踪日志中有大量如下条目:

09-JUN-2020 18:25:21 * service_died * TMF * 12537
09-JUN-2020 18:25:22 * service_register * TMF * 0
09-JUN-2020 18:25:27 * service_died * TMF * 12537
09-JUN-2020 18:25:28 * service_register * TMF * 0
Tue Jun 09 18:25:33 2020
09-JUN-2020 18:25:33 * service_died * TMF * 12537
09-JUN-2020 18:25:34 * service_register * TMF * 0
09-JUN-2020 18:25:39 * service_died * TMF * 12537
09-JUN-2020 18:25:40 * service_register * TMF * 0
Tue Jun 09 18:25:45 2020
09-JUN-2020 18:25:45 * service_died * TMF * 12537
09-JUN-2020 18:25:46 * service_register * TMF * 0
09-JUN-2020 18:25:51 * service_died * TMF * 12537
09-JUN-2020 18:25:52 * service_register * TMF * 0
Tue Jun 09 18:25:57 2020
09-JUN-2020 18:25:57 * service_died * TMF * 12537
09-JUN-2020 18:25:58 * service_register * TMF * 0
09-JUN-2020 18:26:03 * service_died * TMF * 12537
09-JUN-2020 18:26:04 * service_register * TMF * 0
我最近试图解决这一问题,只是对本文中的信息做了一点修改。服务器上的安装程序:

[root@linuxoracle11 trace]# mv /dev/random /dev/xrandom
[root@linuxoracle11 trace]# ln -s /dev/urandom /dev/random
[root@linuxoracle11 trace]# ls -l /dev/*ndom
lrwxrwxrwx 1 root root   12 Jun  9 19:26 /dev/random -> /dev/urandom
crw-rw-rw- 1 root root 1, 9 Jun  9 09:58 /dev/urandom
crw-rw-rw- 1 root root 1, 8 Jun  9 09:58 /dev/xrandom
但是,这并没有解决问题,针对数据库运行的作业仍在中止

最令人恼火的是,有时作业会毫无差错地完成。如果有人能告诉我应该朝哪个方向看,我将不胜感激

编辑: 根据要求,以下是sqlnet.ora文件的内容:

SQLNET.RECV_TIMEOUT=5
SQLNET.INBOUND_CONNECT_TIMEOUT=5
SQLNET.RECV_TIMEOUT=5
SQLNET.INBOUND_CONNECT_TIMEOUT=5
是的,这是安装数据库系统时生成的默认值

还有人认为,这可能是由于“登录风暴”。这是值得怀疑的,因为我们在数据库中几乎没有实际用户。主要是我写的关于在docker容器中运行的那些工作。我查看了oracle doco和一些信息(同样来自Burleson咨询页面),并尝试了以下操作:

SQL> select resource_name, current_utilization, limit_value
  2  from v_$resource_limit
  3  where resource_name in ('processes', 'sessions');

RESOURCE_NAME                  CURRENT_UTILIZATION LIMIT_VALU
------------------------------ ------------------- ----------
processes                      25                  200
sessions                       30                  322
所以我们说的是几十个连接,而不是几百个

Edit2:为了完整起见,这里是堆栈跟踪的一部分:

****** Jun 12, 2020 9:20:32 PM IO Error: Connection reset ******
java.sql.SQLRecoverableException: IO Error: Connection reset
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:752)
    at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666)
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
...

Caused by: java.net.SocketException: Connection reset
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:115)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
    at oracle.net.ns.DataPacket.send(DataPacket.java:209)
    at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:215)
    at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:302)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:249)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:171)
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:89)
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123)
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79)
    at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:429)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:397)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
    at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:437)
    at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:954)
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:639)
    ... 38 more

您应该提供完整的堆栈跟踪 当堆栈跟踪包含:

在oracle.jdbc.driver.T4CConnection.logon上

然后,在身份验证期间,数据库重置了连接。(路上没有任何网络设备)。 这种情况的根本原因(登录风暴)实际上是客户端的问题。由于缺少随机数,客户端无法足够快地进行身份验证。发生这种情况时,您可以:

  • 调整内核参数以在缓冲区中保存更多随机数(客户端)
  • 当JVM使用另一个/dev/*随机设备(客户端)时,请使用该技巧
  • 更改参数SQLNET.INBOUND\u CONNECT\u TIMEOUT以延长服务器等待客户端(db服务器)时的时间窗口
但您收到此错误的原因可能还有其他原因

PS:JVM对第二个“解决方案”(Java bug 6202721)有明确的保护。因为这会危及安全。因此,如果您设置“java.security.egd=file:/dev/uradom”,它会故意忽略您。虽然此设备名称未列入黑名单“java.security.egd=file:/dev//uradom”

以下是sqlnet.ora文件的内容:

SQLNET.RECV_TIMEOUT=5
SQLNET.INBOUND_CONNECT_TIMEOUT=5
SQLNET.RECV_TIMEOUT=5
SQLNET.INBOUND_CONNECT_TIMEOUT=5
这似乎就是问题所在。日志会在
服务注册
五秒钟后反复显示
服务
消息。服务正在一次又一次地从服务器上分离和重新连接。您的JDBC调用work,如果它们恰好在寄存器/死亡对之间开始和结束;如果在报告
服务死亡时启动但尚未完成,则会失败

据我所知,这不应该是一个真正的问题——毕竟,它们将这些值设置为3

这似乎是一个已知的问题;如果您可以访问我的Oracle支持,请查看,这建议将这些设置增加到大于60,或者将它们全部删除—您可能需要跳出数据库来清理它。(如果您没有访问MoS的权限,您可以查看,这不会告诉您太多,但与您在侦听器日志中看到的内容类似。)


还有其他问题,在MoS中搜索会发现文档ID 1206583.1和其他问题,因此可能存在可以解决或修补的错误-这取决于您使用的Oracle的确切版本和修补级别。如果您有疑问,当然可以提出服务请求;假设您有一份支持合同。

当它工作时,需要多长时间?少于5秒?你能包括你的
sqlnet.ora
文件工具吗它有
sent\u timeout
recv\u timeout
设置(大概设置为5)?我已经在帖子中添加了sqlnet.ora的内容。至于连接数据库需要多长时间,我们讨论的是连接数据库通常需要多长时间。我写的作业是在不同的时间创建jdbc连接,用于读取数据、读取目录数据、更新表等等。为什么它有时会工作,有时不会,这就是我需要弄清楚的。它是否工作取决于JDBC调用是否与
service\u
消息一致,大概(再次!)。比较日志应该能说明这一点。通话越短,越有可能逃脱处罚;我认为,一个持续五秒钟以上的手术总是失败的。至于SQL*Plus,这是一个本地遗留连接吗?它不依赖SQL*Net,因此不会受到影响?如果通过服务名称进行连接,您是否发现问题?例如,
sqlplus-usr/pwd@//linuxoracle11:1521/TMF
?@Alex-Poole:比较日志?哪一个?这对我来说是个问题,因为甲骨文松鼠在各种地方记录和发出警报。我通常需要做一个复杂的“查找”来有机会找到一个。您对sqlplus的猜测是正确的。它在服务器上运行,因此不受sqlnet问题的影响