IT Share you

Oracle JDBC 간헐적 연결 문제

shareyou 2020. 12. 7. 21:12
반응형

Oracle JDBC 간헐적 연결 문제


매우 이상한 문제가 발생했습니다. 이것은 Oracle 데이터베이스에 연결하는 JDBC의 매우 간단한 사용입니다.

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

OJDBC14.jar에서 사용할 수없는 JODB5.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 포럼 ( 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 / random 에서 읽기를 차단하는 대신 / dev / urandom 에서 비 차단 읽기를 사용하는 것입니다 . JVM에 다음 시스템 속성 -Djava.security.egd = file : /// dev / urandom 을 추가하면됩니다. 이것은 JDBC 드라이버와 같은 응용 프로그램에 대한 좋은 솔루션이지만 암호 키 생성과 같은 핵심 암호화 작업을 수행하는 응용 프로그램에는 권장되지 않습니다.

다른 솔루션은 엔트로피 수집을 위해 하드웨어 노이즈에 의존하지 않는 플랫폼에 사용할 수있는 다른 임의 시더 구현을 사용하는 것입니다. 이것으로 java.security.SecureRandom 의 기본 동작을 재정의해야 할 수도 있습니다 .

Oracle 서버 측에서 소켓 시간 초과를 늘리는 것도 해결책이 될 수 있지만이를 시도하기 전에 서버 관점에서 부작용을 평가해야합니다.


나는 똑같은 문제에 직면했습니다. Windows Vista에서는 문제를 재현 할 수 없었지만 Ubuntu에서는 '연결 재설정'오류를 지속적으로 재현했습니다.

http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101을 찾았습니다.

해당 포럼의 사용자에 따르면 :

나는 오라클과 티켓을 열었고 이것이 그들이 나에게 말한 것입니다.

java.security.SecureRandom is a standard API provided by sun. Among various methods offered by this class void nextBytes(byte[]) is one. This method is used for generating random bytes. Oracle 11g JDBC drivers use this API to generate random number during login. Users using Linux have been encountering SQLException("Io exception: Connection reset").

The problem is two fold

  1. The JVM tries to list all the files in the /tmp (or alternate tmp directory set by -Djava.io.tmpdir) when SecureRandom.nextBytes(byte[]) is invoked. If the number of files is large the method takes a long time to respond and hence cause the server to timeout

  2. The method void nextBytes(byte[]) uses /dev/random on Linux and on some machines which lack the random number generating hardware the operation slows down to the extent of bringing the whole login process to a halt. Ultimately the the user encounters SQLException("Io exception: Connection reset")

Users upgrading to 11g can encounter this issue if the underlying OS is Linux which is running on a faulty hardware.

Cause The cause of this has not yet been determined exactly. It could either be a problem in your hardware or the fact that for some reason the software cannot read from dev/random

Solution Change the setup for your application, so you add the next parameter to the java command:

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

We made this change in our java.security file and it has gotten rid of the error.

which solved my problem.


A "connection reset" error message generally means that the other side has aborted the connection during the attempt to create a connection (the handshake). This has a lot of possible causes. A bug in the JDBC driver, a timeout at the DB side, a restart of the database, the DB being run out of available connections, poor network quality, bad virusscanner/firewall/proxy, etc.

As it happens intermittely, a bug in the JDBC driver can be less or more excluded. Left behind the remaining possible causes. I suggest to start with looking in the logs of the DB server.


It's hard to say, but if I would check the actual version of the JDBC driver. Make sure it's 11.1.0.6.

Oracle doesn't include the database version in the filename. So the driver for 11.2 is the exact same name as the driver for 11.1 - ojdbc5.jar. I would extract the driver jar file, and find the MANIFEST.MF file, this will contain some version information. Make sure the version of the JDBC driver matches the version of your database. I suspect it may be a version issue, since there isn't a jar file named ojdbc14.jar on Oracle's 11.1.0.6 download page.

If the version matches - I'm out of ideas :)


Other thing that was causing me this problem was having the HOSTNAME settings wrong. My connection attempt was hanged at:

"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)

So make sure you have an entry for your hostname in /etc/hosts/.

If you issue a hostname command like this:

$ hostname
my.server.com

You need a line in your /etc/hosts:

127.0.0.1 my my.server.com

I found this link for the same problem with 64bit system, driver jdbc 11g and connection reset: http://forums.oracle.com/forums/thread.jspa?messageID=3793101


Just to clarify - at least from what we found on our side! It is an issue with the setup of the randomizer for Linux in the JDK distribution - and we found it in Java6, not sure about Java7. The syntax for linux for the randomizer is file:///dev/urandom, but the entry in the file is (probably left/copied from Windows) as file:/dev/urandom. So then Java probably falls back on the default, which happens to be /dev/random. And which doesn't work on a headless machine!!!


The root cause of this problem has to do with user authentication versions. For each database user, multiple password verifiers are kept in the database. Typically when you upgrade your database, a new password verifier will be added to the list, a stronger one. The following query shows the password verifier versions that are available for each user. For example:

SQL> SELECT PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME='SCOTT';

PASSWORD_VERSIONS
-----------------
11G 12C

When upgrading to a newer driver you can use a newer version of the verifier because the driver and server negotiate the strongest possible verifier to to be used. This newer version of the verifier will be more secure and will involve generating larger random numbers or using more complex hashing functions which can explain why you see issues while establishing JDBC connections. As mentioned by other responses using /dev/urandom normally resolves these issues. You can also decide to downgrade your password verifier and make the newer driver use the same older password verifier that your previous driver was using. For example if you want to use the 10G password verifier (for testing purposes only), first you need to make sure it's available for your user. Set SQLNET.ALLOWED_LOGON_VERSION_SERVER=8 in sqlnet.ora on the server. Then:

SQL> alter user scott identified by "tiger";

User altered.

SQL> SELECT PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME='SCOTT';
PASSWORD_VERSIONS
-----------------
10G 11G 12C

Then you can force the JDBC thin driver to use the 10G verifier by setting this JDBC property oracle.jdbc.thinLogonCapability="o3". If you run into the error "ORA-28040: No matching authentication protocol" then that means your server is not allowing the 10G verifier to be used. If that's the case then you need to check your configuration again.


Note that the suggested solution of using /dev/urandom did work the first time for me but didn't work always after that.

DBA at my firm switched of 'SQL* net banners' and that fixed it permanently for me with or without the above.

I don't know what 'SQL* net banners' are, but am hoping by putting this information here that if you have(are) a DBA he(you) would know what to do.


Disabling SQL Net Banners saved us.


-Djava.security.egd=file:/dev/./urandom should be right! not -Djava.security.egd=file:/dev/../dev/urandom or -Djava.security.egd=file:///dev/urandom


As per Bug https://bugs.openjdk.java.net/browse/JDK-6202721

Java will not consder -Djava.security.egd=file:/dev/urandom

It should be -Djava.security.egd=file:/dev/./urandom


OracleXETNSListener - this service has to be started if it was disabled.

run -> services.msc 

and look out for that services

참고URL : https://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue

반응형