SQL 可恢复异常:I/O 异常:连接重置

2022-09-01 06:25:29

昨天晚上,我带着一个由我编写的正在运行的Java程序离开了办公室。它应该使用JDBC连接将大量记录插入到我们公司数据库(Oracle)中。今天早上当我回到工作岗位时,我看到了这个错误(被一个尝试捕获捕获):

java.sql.SQLRecoverableException: I/O Exception: Connection reset

该程序在遇到此问题之前几乎编写了所有记录,但是如果它发生得很早(就在我晚上离开办公室后的几分钟)怎么办?我无法理解发生了什么,我联系了我的数据库管理员,他说数据库上没有特别的问题。

关于发生了什么以及我能做些什么来避免它的任何想法?


答案 1

该错误发生在某些 RedHat 发行版上。您唯一需要做的就是使用参数 java.security.egd=file:///dev/urandom 运行您的应用程序:

java -Djava.security.egd=file:///dev/urandom [your command]

答案 2

我想为玉米片 - 索里亚诺的解决方案提供一个补充答案......

我最近搜索了一个问题,即Java编写的应用程序(实际上是Talend© ELT作业)想要连接到Oracle数据库(11g及以上),然后随机失败。操作系统既是RedHat Enterprise也是CentOS。作业运行得非常及时(不超过半分钟),并且经常发生(大约每 5 分钟运行一次)。

有时,在夜间作为工作时间,在数据库密集型工作使用期间作为懒惰工作使用,只需一个单词随机,连接失败,并显示以下消息:

Exception in component tOracleConnection_1
java.sql.SQLRecoverableException: Io exception: Connection reset
        at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:101)
        at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:112)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:173)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:229)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:458)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:411)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:490)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:202)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:33)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:465)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:208)
    and StackTrace follow ...

##Problem解释:##

如此所述

Oracle 连接需要一些随机数来假定良好的安全级别。Linux随机数生成器生成一些基于键盘和鼠标活动(以及其他)的数字,并将它们放在堆栈中。你会授予我,在服务器上,没有大量的此类活动。因此,软件使用的随机数可能比生成器可以产生的随机数更多。

当池为空时,来自 /dev/random 的读取操作将被阻塞,直到收集到其他环境噪声。并且 Oracle 连接处于超时状态(默认为 60 秒)。

##Solution 1 - 特定于一个应用解决方案##

解决方案是在启动时为JVM添加两个参数:

-Djava.security.egd=file:/dev/./urandom
-Dsecurerandom.source=file:/dev/./urandom

注意:“/./”很重要,不要删除它!

因此,启动命令行可以是:

java -Djava.security.egd=file:/dev/./urandom -Dsecurerandom.source=file:/dev/./urandom -cp <classpath directives> appMainClass <app options and parameters>

此解决方案的一个缺点是生成的数字的安全性稍低,因为随机性会受到影响。如果您不在军事或秘密相关行业工作,此解决方案可能是您的。

##Solution 2 - 通用 Java JVM 解决方案##

如此所述

解决方案 1 中给出的两个指令都可以放在 Java 安全设置文件中。

看看$JAVA_HOME/jre/lib/security/java.security

更改行

securerandom.source=file:/dev/random

securerandom.source=file:/dev/urandom

更改将立即对正在运行的新应用程序生效。

至于解决方案#1,此解决方案的一个缺点是生成的数字的安全性较低,因为随机性受到影响。这一次,它是全球JVM的影响。至于解决方案#1,如果您不在军事或秘密相关行业工作,此解决方案可能是您的。

理想情况下,我们应该在Java 5之后使用“file:/dev/./urandom”,因为之前的路径将再次指向/dev/random。

报告的错误 : https://bugs.openjdk.java.net/browse/JDK-6202721

##Solution 3 - 硬件解决方案##

光盘:我没有链接到任何硬件供应商或产品...

如果您需要达到高质量的随机性级别,则可以用一个硬件替换Linux随机数生成器软件。

此处提供了一些信息。

问候

托马斯


推荐