昨天晚上,我离开了办公室,运行了一个由我编写的Java程序。它应该使用JDBC连接将大量记录插入到我们的公司数据库(Oracle)中。今天早上当我回来工作时,我看到了这个错误(被try-catch捕获):
java.sql.SQLRecoverableException: I/O Exception: Connection reset
该程序在得到这个问题之前写了几乎所有的记录,但如果它发生得很早(我晚上离开办公室几分钟后)怎么办?我无法理解发生了什么,我联系了我的数据库管理员,他说数据库没有特别的问题。
对发生的事情有什么想法,我该怎么办才能避免它?
答案 0 :(得分:23)
某些RedHat发行版上发生错误。您唯一需要做的就是使用参数 java.security.egd = file:/// dev / urandom 运行您的应用程序:
java -Djava.security.egd=file:///dev/urandom [your command]
答案 1 :(得分:13)
这只是意味着后端(DBMS)中的某些东西由于资源不可用而决定停止工作。 它与您的代码或插入数量无关。 您可以在此处阅读有关类似问题的更多信息:
这可能无法解答您的问题,但您会了解为什么会发生这种情况。您可以与您的DBA进一步讨论,看看您的案例中是否有特定的内容。
答案 2 :(得分:11)
我想提出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 ...
详细here
Oracle连接需要一些随机数来承担良好的安全级别。 Linux随机数生成器生成一些基于键盘和鼠标活动的数字(以及其他)并将它们放在堆栈中。您将在服务器上授予我不存在大量此类活动的权限。因此,软件使用比生成器更多的随机数就可能发生。
当池为空时,从/ dev / random读取将阻塞,直到收集到额外的环境噪声。 Oracle连接超时(默认为60秒)。
解决方案是在启动时添加两个给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>
此解决方案的一个缺点是随着随机性的影响,生成的数字安全性稍差。如果您不在军事或秘密相关行业工作,这个解决方案可以是您的。
正如here
所解释的那样解决方案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
Disclamer:我没有与任何硬件供应商或产品相关联......
如果您需要达到高质量的随机性级别,您可以通过硬件更换Linux随机数生成器软件。
有些信息可供here。
此致
托马斯
答案 3 :(得分:5)
解决方案
更改应用程序的设置,因此java命令旁边的参数[ -Djava.security.egd = file:/ dev /../ dev / urandom ]:
java -Djava.security.egd = file:/ dev /../ dev / urandom [your command]
答案 4 :(得分:4)
我们在从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。
export JAVA_OPTS =“$ JAVA_OPTS -Djava.security.egd = file:/// dev / urandom”
答案 5 :(得分:2)
您的例外说明了所有“连接重置”。 您的Java进程和数据库服务器之间的连接已丢失,这几乎可能是出于任何原因(如网络问题)。 SQLRecoverableException只是意味着它是可恢复的,但根本原因是连接重置。
答案 6 :(得分:1)
在Spark作业中从Oracle读取时,我遇到了类似的情况。此连接重置错误是由Oracle服务器与所使用的JDBC驱动程序之间的不兼容引起的。值得检查。
答案 7 :(得分:0)
在运行命令中添加Java安全性
java -jar -Djava.security.egd="file:///dev/urandom" yourjarfilename.jar