33

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

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

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

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

4

8 回答 8

34

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

java -Djava.security.egd=file:///dev/urandom [your command]
于 2016-09-05T14:18:15.623 回答
28

我想为nacho-soriano的解决方案提供一个补充答案......

我最近搜索解决一个问题,即 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 ...

问题解释:

如此处详述

Oracle 连接需要一些随机数来假设良好的安全级别。Linux 随机数生成器根据键盘和鼠标活动(以及其他)生成一些数字并将它们放在堆栈中。你会同意我,在服务器上,这样的活动并不多。因此,软件使用的随机数可能比生成器产生的多。

当池为空时,来自 /dev/random 的读取将被阻塞,直到收集到额外的环境噪音。并且 Oracle 连接超时(默认为 60 秒)。

解决方案 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>

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

解决方案 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

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

免责声明:我与任何硬件供应商或产品都没有联系...

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

一些信息可在此处获得。

问候

托马斯

于 2018-04-11T12:57:10.663 回答
20

这仅仅意味着后端( DBMS )中的某些东西由于资源不可用等原因决定停止工作。它与您的代码或插入次数无关。您可以在此处阅读有关类似问题的更多信息:

这可能无法回答您的问题,但您会了解为什么会发生这种情况。您可以与您的 DBA 进一步讨论,看看您的情况是否有具体问题。

于 2011-05-24T12:41:06.153 回答
6

解决方案
更改您的应用程序的设置,以便在 java 命令旁边使用此参数 [ -Djava.security.egd=file:/dev/../dev/urandom ]:

java -Djava.security.egd=file:/dev/../dev/urandom [你的命令]

参考:- https://community.oracle.com/thread/943911

于 2016-08-30T17:38:53.380 回答
5

从 11g 升级到 12c 后,我们间歇性地遇到这些错误,而我们的 java 在 1.6 上。

我们的解决方法是将 java 和 jdbc 从 6 升级到 7

export JAVA_HOME='/usr/java1.7'

export CLASSPATH=/u01/app/oracle/product/12.1.0/dbhome_1/jdbc/libojdbc7.jar:$CLASSPATH 

几天后,仍然间歇性连接重置。

我们最终删除了上面所有的 java 7。Java 6 很好。通过将此添加到我们的用户 bash_profile 来解决问题。

我们遇到错误的 groovy 脚本在我们的批处理 VM 服务器上使用 /dev/random。下面强制 java 和 groovy 使用 /dev/urandom。

导出 JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:///dev/urandom"

于 2015-03-17T18:30:18.660 回答
2

你的例外说这一切都是“连接重置”。您的 java 进程和数据库服务器之间的连接丢失了,这几乎可能由于任何原因(如网络问题)而发生。SQLRecoverableException只是意味着它可以恢复,但根本原因是连接重置

于 2011-05-24T12:36:43.120 回答
1

在 Spark 作业中从 Oracle 读取数据时,我遇到了类似的情况。此连接重置错误是由 Oracle 服务器和使用的 JDBC 驱动程序之间的不兼容引起的。值得检查一下。

于 2020-06-30T08:52:35.587 回答
0

在运行命令中添加 java 安全性

java -jar -Djava.security.egd="file:///dev/urandom" yourjarfilename.jar

于 2020-09-24T05:51:08.280 回答