Oracle JDBC间歇性连接问题

我遇到一个非常奇怪的问题这是一个非常简单的使用JDBC连接到Oracle数据库

OS: Ubuntu Java Version: 1.5.0_16-b02 1.6.0_17-b04 Database: Oracle 11g Release 11.1.0.6.0 

当我使用jar文件OJDBC14.jar它每次连接到数据库当我使用jar文件OJDBC5.jar它连接了一些时间和其他时间它会抛出一个错误(如下所示)如果我重新编译与Java 6和使用OJDBC6.jar我得到了与OJDBC5.jar相同的结果

我需要JODB5.jar中的特定function,这些function在OJDBC14.jar中不可用

有任何想法吗

错误

 > Connecting to oracle java.sql.SQLException: Io exception: Connection reset at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:74) at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:110) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:171) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:227) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:494) 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:474) at java.sql.DriverManager.getConnection(DriverManager.java:525) at java.sql.DriverManager.getConnection(DriverManager.java:171) at TestConnect.main(TestConnect.java:13) 

以下是我正在使用的代码

 import java.io.*; import java.sql.*; public class TestConnect { public static void main(String[] args) { try { System.out.println("Connecting to oracle"); Connection con=null; Class.forName("oracle.jdbc.driver.OracleDriver"); con=DriverManager.getConnection( "jdbc:oracle:thin:@172.16.48.100:1535:sample", "JOHN", "90009000"); System.out.println("Connected to oracle"); con.close(); System.out.println("Goodbye"); } catch(Exception e) { e.printStackTrace(); } } } 

在某些OTN论坛中提供了解决此问题的解决scheme( https://kr.forums.oracle.com/forums/thread.jspa?messageID=3699989 )。 但是,问题的根本原因没有解释。 以下是我试图解释问题的根源。

Oracle JDBC驱动程序以安全的方式与Oracle服务器进行通信。 驱动程序使用java.security.SecureRandom类来收集确保通信的熵。 这个类依靠本地平台支持来收集熵。

是由操作系统或应用程序收集/生成的用于密码学或需要随机数据的其他用途的随机性。 这种随机性通常是从硬件来源收集的,无论是硬件噪声,audio数据,鼠标移动还是专门提供的随机生成器。 内核收集熵并将其存储为熵池,并通过特殊文件/ dev / random/ dev / urandom将随机字符数据提供给操作系统进程或应用程序。

/ dev / random读取所请求的比特/字节数量的熵池,提供密码操作中经常需要的高度随机性。 如果熵池被完全耗尽并且没有足够的熵,则对/ dev / random块进行读取操作,直到收集到额外的熵为止。 由于这个原因,从/ dev / random读取的应用程序可能会阻塞一段随机的时间。

与上面相反,从/ dev / urandom读取不会阻塞。 从/ dev / urandom中读取也会消耗熵池,但是当熵不够时,它不会阻塞,而是重用部分读取的随机数据中的位。 据说这对密码分析攻击很敏感。 这是一个理论上的可能性,因此从/ dev / urandom中读取密码操作中的随机性是不鼓励的。

缺省情况下, java.security.SecureRandom类从/ dev / random文件读取,因此有时会阻塞随机时间段。 现在,如果读取操作没有返回所需的时间,Oracle服务器会超时客户端(本例中为jdbc驱动程序),并通过closures套接字来终止通信。 客户端在尝试从阻塞调用返回后恢复通信时遇到IOexception。 这个问题可能会在任何平台上随机发生,特别是熵从硬件噪声中收集的地方。

正如OTN论坛中所build议的,解决此问题的方法是覆盖java.security.SecureRandom类的默认行为,以使用从/ dev / urandom进行非阻塞读取而不是从/ dev / random进行阻止读取。 这可以通过将以下系统属性-Djava.security.egd = file:/// dev / urandom添加到JVM来完成。 虽然这对于像JDBC驱动程序这样的应用程序来说是一个很好的解决scheme,但是对于执行诸如encryption密钥生成的核心密码操作的应用程序来说,这是不鼓励的。

其他解决scheme可以是使用可用于平台的不同随机播种器实现,其不依赖硬件噪声来收集熵。 有了这个,你可能仍然需要重写java.security.SecureRandom的默认行为。

增加Oracle服务器端的套接字超时也可能是一个解决scheme,但是在尝试这个之前,应该从服务器的angular度来评估副作用。

我面对完全相同的问题。 随着Windows Vista的我不能重现这个问题,但在Ubuntu上,我不断重复“连接重置”错误。

我发现http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101

根据该论坛的用户:

我与甲骨文开了一张票,这就是他们告诉我的。

java.security.SecureRandom是sun提供的标准API。 在这个类提供的各种方法中,void nextBytes(byte [])是一个。 此方法用于生成随机字节。 Oracle 11g JDBC驱动程序使用此API在login期间生成随机数。 使用Linux的用户遇到了SQLException(“exception:连接重置”)。

问题是双重的

  1. 当调用SecureRandom.nextBytes(byte [])时,JVM尝试列出/ tmp(或由-Djava.io.tmpdir设置的备用tmp目录)中的所有文件。 如果文件数量很大,则该方法需要很长时间才能响应,从而导致服务器超时

  2. void nextBytes(byte [])方法在Linux上使用/ dev / random,在一些缺less随机数生成硬件的机器上,操作速度减慢到整个login过程停止的程度。 最终,用户遇到SQLException(“Ioexception:连接重置”)

如果底层操作系统是运行在故障硬件上的Linux,则升级到11g的用户可能会遇到此问题。

原因原因尚未完全确定。 这可能是您的硬件有问题,或者由于某些原因,软件无法从dev / random中读取

解决scheme更改应用程序的设置,以便将下一个参数添加到java命令中:

-Djava.security.egd =文件是:/ dev /../开发/ urandom的

我们在java.security文件中做了这个改变,并且已经清除了错误。

这解决了我的问题。

“连接重置”错误消息通常意味着另一方在尝试创build连接(握手)期间中止了连接。 这有很多可能的原因。 JDBC驱动程序中的错误,数据库端超时,数据库重新启动,数据库用尽连接,networking质量差,恶意软件扫描器/防火墙/代理服务器等等。

正如间歇性地发生的那样,JDBC驱动程序中的一个错误可能会被排除在外。 留下剩余的可能原因。 我build议先查看数据库服务器的日志。

很难说,但如果我要检查JDBC驱动程序的实际版本。 确保它是11.1.0.6。

Oracle不包含文件名中的数据库版本。 所以11.2的驱动程序与11.1 – ojdbc5.jar的驱动程序完全相同。 我将提取驱动程序jar文件,并findMANIFEST.MF文件,这将包含一些版本信息。 确保JDBC驱动程序的版本与数据库的版本相匹配。 我怀疑这可能是一个版本问题,因为在Oracle的11.1.0.6 下载页面上没有名为ojdbc14.jar的jar文件。

如果版本匹配 – 我没有想法:)

我发现这个链接与64位系统,驱动程序jdbc 11g和连接重置相同的问题: http : //forums.oracle.com/forums/thread.jspa?messageID=3793101

只是为了澄清 – 至less从我们发现在我们身边! 这是在JDK发行版中为Linux设置随机发生器的一个问题 – 我们在Java6中发现它,不确定Java7。 用于随机数发生器的linux的语法是file:/// dev / urandom,但是文件中的条目是(可能是从/从Windows复制的)文件:/ dev / urandom。 那么Java可能会回落到默认值,这恰好是/ dev / random。 哪个在无头机器上不起作用!

其他导致我这个问题的事情是有HOSTNAME设置错误。 我的连接尝试被绞死在:

 "main" prio=10 tid=0x00007f7cc8009000 nid=0x2f3a runnable [0x00007f7cce69e000] java.lang.Thread.State: RUNNABLE at java.net.Inet4AddressImpl.getLocalHostName(Native Method) at java.net.InetAddress.getLocalHost(InetAddress.java:1444) at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:176) at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:162) at java.security.AccessController.doPrivileged(Native Method) 

因此,请确保在/etc/hosts/有一个用于主机名的条目。

如果你像这样发出一个hostname命令:

 $ hostname my.server.com 

你需要在/etc/hosts有一行:

 127.0.0.1 my my.server.com 

请注意,使用/ dev / urandom的build议解决scheme对我来说是第一次工作,但在此之后并不总是工作。

我公司的DBA转换了“SQL *networking横幅”,并且在有或没有上述情况下为我永久地修复了这个问题。

我不知道'SQL *networking横幅'是什么,但希望把这个信息放在这里,如果你有一个DBA,他(你)会知道该怎么做。

禁用SQLnetworking横幅节省了我们

-Djava.security.egd = file:/ dev /./ urandom应该是正确的! 不是-Djava.security.egd = file:/ dev /../ dev / urandom或-Djava.security.egd = file:/// dev / urandom

按照Bug https://bugs.openjdk.java.net/browse/JDK-6202721

Java不会consder -Djava.security.egd = file:/ dev / urandom

它应该是-Djava.security.egd = file:/ dev /./ urandom

OracleXETNSListener – 如果该服务被禁用,则必须启动该服务。

 run -> services.msc 

并寻找那些服务