61 votes

Problème de connexion intermittente à Oracle JDBC

Je rencontre un problème très étrange Il s'agit d'une utilisation très simple de JDBC pour se connecter à une base de données Oracle.

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

Lorsque j'utilise le fichier jar OJDBC14.jar il se connecte à la base de données à chaque fois Lorsque j'utilise le fichier jar OJDBC5.jar il se connecte parfois et parfois il affiche une erreur (voir ci-dessous). Si je recompile avec Java 6 et utilise OJDBC6.jar J'obtiens les mêmes résultats que OJDBC5.jar

J'ai besoin de fonctionnalités spécifiques dans JODB5.jar qui ne sont pas disponibles dans OJDBC14.jar.

Des idées ?

Erreur

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

Code

Voici le code que j'utilise

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(); }
    }
}

0 votes

J'ai le même problème, est-il résolu ?

92voto

Vikas Nalwar Points 2552

Il existe une solution à ce problème dans certains des forums du RTO ( https://kr.forums.oracle.com/forums/thread.jspa?messageID=3699989 ). Mais, la cause profonde du problème n'est pas expliquée. Voici ma tentative d'expliquer la cause fondamentale du problème.

Les pilotes Oracle JDBC communiquent avec le serveur Oracle de manière sécurisée. Les pilotes utilisent le java.security.SecureRandom pour rassembler l'entropie afin de sécuriser la communication. Cette classe s'appuie sur le support de la plateforme native pour collecter l'entropie.

Entropie est le caractère aléatoire collecté/généré par un système d'exploitation ou une application pour être utilisé dans la cryptographie ou d'autres utilisations qui nécessitent des données aléatoires. Ce caractère aléatoire est souvent collecté à partir de sources matérielles, soit à partir des bruits du matériel, des données audio, des mouvements de la souris ou de générateurs de caractère aléatoire spécialement fournis. Le noyau rassemble l'entropie, la stocke dans un pool d'entropie et met les données de caractères aléatoires à la disposition des processus ou des applications du système d'exploitation par le biais de fichiers spéciaux. /dev/random y /dev/urandom .

Lecture de /dev/random draine la réserve d'entropie avec la quantité demandée de bits/octets, fournissant un haut degré d'aléatoire souvent souhaité dans les opérations cryptographiques. Dans le cas où la réserve d'entropie est complètement vidée et qu'il n'y a pas suffisamment d'entropie disponible, l'opération de lecture sur le fichier /dev/random blocs jusqu'à ce qu'une entropie supplémentaire soit recueillie. De ce fait, les applications lisant des /dev/random peut être bloqué pendant une période de temps aléatoire.

Contrairement à ce qui précède, la lecture du /dev/urandom ne bloque pas. La lecture de /dev/urandom Mais lorsqu'il n'y a pas assez d'entropie, il ne bloque pas mais réutilise les bits des données aléatoires partiellement lues. On dit que cette méthode est sensible aux attaques cryptanalytiques. Il s'agit d'une possibilité théorique et il est donc déconseillé de lire à partir de /dev/urandom pour rassembler le caractère aléatoire dans les opérations cryptographiques.

El java.security.SecureRandom par défaut, lit à partir du fichier /dev/random et, par conséquent, se bloque parfois pendant une période de temps aléatoire. Maintenant, si l'opération de lecture n'est pas retournée pendant un certain temps, le serveur Oracle bloque le client (les pilotes jdbc, dans ce cas) et interrompt la communication en fermant le socket de son côté. Lorsque le client tente de reprendre la communication après le retour de l'appel bloquant, il rencontre l'exception IO. Ce problème peut se produire de manière aléatoire sur n'importe quelle plate-forme, en particulier lorsque l'entropie provient de bruits matériels.

Comme il a été suggéré dans le forum OTN, la solution à ce problème consiste à modifier le comportement par défaut de la fonction java.security.SecureRandom pour utiliser la lecture non bloquante de la classe /dev/urandom au lieu de la lecture bloquante de /dev/random . Cela peut être fait en ajoutant la propriété système suivante -Djava.security.egd=file:///dev/urandom à la JVM. Bien qu'il s'agisse d'une bonne solution pour les applications telles que les pilotes JDBC, elle est déconseillée pour les applications qui effectuent des opérations cryptographiques essentielles telles que la génération de clés cryptographiques.

D'autres solutions pourraient consister à utiliser différentes implémentations de semeurs aléatoires disponibles pour la plateforme qui ne s'appuient pas sur les bruits matériels pour collecter l'entropie. Dans ce cas, vous devrez peut-être encore modifier le comportement par défaut de la fonction java.security.SecureRandom .

L'augmentation du délai d'attente des sockets du côté du serveur Oracle peut également être une solution, mais les effets secondaires doivent être évalués du point de vue du serveur avant d'essayer.

0 votes

Le même problème/solution est rapporté dans un document d'Oracle pour configurer swingbench, un générateur de charge pour les bases de données Oracle à la page 7 : oracle.com/technetwork/database/database-appliance/

0 votes

Il y a quelques autres endroits où cette question est mentionnée, notamment : stackoverflow.com/questions/5503063/oracle-getconnection-slow

0 votes

Que pensez-vous de cela ? freelists.org/post/oracle-l/ ? Je suppose que la prochaine réponse est liée à cela ?

19voto

Camilla Points 61

Je rencontrais exactement le même problème. Sous Windows Vista, je n'ai pas pu reproduire le problème, mais sous Ubuntu, j'ai constamment reproduit l'erreur de réinitialisation de la connexion.

J'ai trouvé http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101

Selon un utilisateur de ce forum :

J'ai ouvert un ticket avec Oracle et voici ce qu'ils m'ont répondu.

java.security.SecureRandom est une API standard fournie par Sun. Parmi diverses méthodes offertes par cette classe, on trouve void nextBytes(byte[]). Cette méthode est utilisée pour générer des octets aléatoires. Les pilotes JDBC Oracle 11g d'Oracle 11g utilisent cette API pour générer un nombre aléatoire lors de la connexion. Les utilisateurs utilisant Linux ont rencontré SQLException("Io exception : Connection reset").

Le problème est double

  1. La JVM tente de lister tous les fichiers du répertoire /tmp (ou du répertoire tmp alternatif défini par -Djava.io.tmpdir) lorsque SecureRandom.nextBytes(byte[]) est invoqué. Si le nombre de fichiers est important, la méthode prend beaucoup de temps pour répondre, ce qui peut provoquer un blocage du serveur. temps de réponse, ce qui entraîne un dépassement de délai pour le serveur.

  2. La méthode void nextBytes(byte[]) utilise /dev/random sous Linux et sur certaines machines qui n'ont pas de matériel de génération de nombres aléatoires, l'opération de génération de nombres aléatoires peut s'avérer difficile. l'opération ralentit au point d'interrompre tout le processus de connexion à l'arrêt. Finalement, l'utilisateur rencontre une SQLException("Io exception : Connexion réinitialisée")

Les utilisateurs effectuant une mise à niveau vers 11g peuvent rencontrer ce problème si le système d'exploitation sous-jacent est Linux et s'exécute sur un matériel défectueux. sous-jacent est Linux qui fonctionne sur un matériel défectueux.

Cause La cause de ce problème n'a pas encore été déterminée avec précision. Il peut s'agir un problème dans votre matériel ou le fait que pour une raison quelconque le logiciel ne peut pas lire le fichier dev/random

Solution Modifiez la configuration de votre application, afin d'ajouter le paramètre suivant à la commande java :

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

Nous avons fait ce changement dans notre fichier java.security et cela nous a débarrassé de l'erreur. l'erreur.

ce qui a résolu mon problème.

6voto

BalusC Points 498232

Un message d'erreur de "réinitialisation de la connexion" signifie généralement que l'autre partie a interrompu la connexion pendant la tentative de création d'une connexion (le "handshake"). Les causes possibles sont nombreuses. Un bogue dans le pilote JDBC, un dépassement de délai du côté de la base de données, un redémarrage de la base de données, l'épuisement des connexions disponibles de la base de données, une mauvaise qualité de réseau, un mauvais antivirus/pare-feu/proxy, etc.

Comme cela arrive par intermittence, un bug dans le pilote JDBC peut être plus ou moins exclu. Il reste les autres causes possibles. Je suggère de commencer par regarder dans les logs du serveur de base de données.

3voto

Steve K Points 10475

C'est difficile à dire, mais si je vérifiais la version actuelle du pilote JDBC. Assurez-vous que c'est 11.1.0.6.

Oracle n'inclut pas la version de la base de données dans le nom du fichier. Ainsi, le pilote pour 11.2 porte exactement le même nom que le pilote pour 11.1 - ojdbc5.jar. J'extrairais le fichier jar du pilote et trouverais le fichier MANIFEST.MF, qui contient des informations sur la version. Assurez-vous que la version du pilote JDBC correspond à la version de votre base de données. Je pense qu'il s'agit d'un problème de version, car il n'y a pas de fichier jar nommé ojdbc14.jar dans la version 11.1.0.6 d'Oracle. télécharger página.

Si la version correspond - je suis à court d'idées :)

1voto

am yourks Points 11

J'ai trouvé ce lien pour le même problème avec un système 64bit, le pilote jdbc 11g et la réinitialisation de la connexion : http://forums.oracle.com/forums/thread.jspa?messageID=3793101

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X