Oracle JDBC间歇性连接问题

Lip*_*ska 59 java 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
Run Code Online (Sandbox Code Playgroud)

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

我需要JODB5.jar中的特定功能,这些功能在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)
Run Code Online (Sandbox Code Playgroud)

以下是我正在使用的代码

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(); }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dro*_*ona 91

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

Oracle JDBC驱动程序以安全的方式与Oracle服务器通信.驱动程序使用 java.security.SecureRandom类来收集熵以保护通信.此类依赖于本机平台支持来收集熵.

是由操作系统或应用程序收集/生成的随机性,用于加密或需要随机数据的其他用途.这种随机性通常是从硬件噪声源,硬件噪声,音频数据,鼠标移动或专门提供的随机性生成器中收集的.内核收集熵并存储它是一个熵池,并通过特殊文件/ dev/random/ dev/urandom使随机字符数据可供操作系统进程或应用程序使用.

/ dev/random读取使用所请求的比特/字节量来消耗熵池,从而提供加密操作中经常需要的高度随机性.在这种情况下,如果熵池被完全耗尽并且没有足够的熵,则对/ dev/random块进行读取操作,直到收集到额外的熵.因此,从/ dev/random读取的应用程序可能会阻塞一段随机时间.

与上述相反,从/ dev/urandom读取不会阻止.从/ dev/urandom读取也会消耗熵池,但是当缺少足够的熵时,它不会阻塞,而是重用来自部分读取的随机数据的位.据说这很容易受到密码分析攻击.这是一种理论上的可能性,因此不鼓励从/ dev/urandom读取以在加密操作中收集随机性.

java.security.SecureRandom中类,默认情况下,从读出的/ dev /随机文件,因此有时对的时间随机时段块.现在,如果读取操作没有返回所需的时间,则Oracle服务器会超时客户端(在本例中为jdbc驱动程序)并通过从其末端关闭套接字来中断通信.从阻塞调用返回后尝试恢复通信的客户端遇到IO异常.此问题可能在任何平台上随机发生,尤其是从硬件噪声中收集熵的情况.

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

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

增加Oracle服务器端的套接字超时也可以是一种解决方案,但在尝试此操作之前,应从服务器的角度评估副作用.


小智 17

我面临着同样的问题.使用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在登录期间生成随机数.使用Linux的用户遇到了SQLException("Io exception:Connection reset").

这个问题有两个问题

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

  2. 方法void nextBytes(byte [])在Linux上使用/ dev/random,在缺少随机数生成硬件的某些机器上,操作速度降低到使整个登录过程停止的程度.最终用户遇到SQLException("Io exception:Connection reset")

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

原因尚未确切地确定原因.它可能是您硬件中的问题,也可能是由于某种原因软件无法从dev/random读取的事实

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

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

我们在java.security文件中进行了此更改,它已经摆脱了错误.

这解决了我的问题.


Bal*_*usC 6

“连接重置”错误消息通常表示在尝试创建连接(握手)期间,另一端已中止连接。这有很多可能的原因。JDBC驱动程序中的错误,数据库侧的超时,数据库的重新启动,可用的连接用尽了数据库,网络质量差,病毒扫描程序/防火墙/代理错误等。

由于它是间歇性发生的,因此JDBC驱动程序中的错误可能会或多或少地被排除。遗留下来的可能原因。我建议从查找数据库服务器的日志开始。


Ste*_*e K 3

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

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

如果版本匹配 - 我没有主意了:)