Oracle JDBC неустойчивая проблема соединения - PullRequest
59 голосов
/ 24 февраля 2010

У меня очень странная проблема Это очень простое использование 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, которые недоступны в OJDBC14.jar

Любые идеи

Error

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

Ответы [ 13 ]

91 голосов
/ 14 ноября 2011

Существует решение для этой проблемы на некоторых форумах 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 / random и, следовательно, иногда блокируется в течение произвольного периода времени. Теперь, если операция чтения не возвращается в течение необходимого периода времени, сервер Oracle тайм-аут клиента (в данном случае драйверы jdbc) и прекращает связь, закрывая сокет с его конца. Когда клиент пытается возобновить связь после возврата из блокирующего вызова, клиент обнаруживает исключение ввода-вывода. Эта проблема может возникать случайным образом на любой платформе, особенно если энтропия собирается из аппаратных помех.

Как предлагается на форуме OTN, решение этой проблемы состоит в переопределении поведения по умолчанию java.security.SecureRandom для использования неблокирующего чтения из / dev / urandom вместо блокировки чтения из / dev / random . Это можно сделать, добавив следующее системное свойство -Djava.security.egd = file: /// dev / urandom в JVM. Хотя это хорошее решение для приложений, таких как драйверы JDBC, оно не рекомендуется для приложений, которые выполняют основные криптографические операции, такие как генерация криптографических ключей.

Другие решения могут заключаться в использовании различных реализаций случайных сеялок, доступных для платформы, которые не полагаются на аппаратные шумы для сбора энтропии. При этом вам все равно может потребоваться переопределить поведение по умолчанию java.security.SecureRandom .

Увеличение времени ожидания сокета на стороне сервера Oracle также может быть решением, но побочные эффекты должны быть оценены с точки зрения сервера, прежде чем пытаться это сделать.

17 голосов
/ 29 марта 2010

Я столкнулся с точно такой же проблемой. В Windows Vista я не мог воспроизвести проблему, но в Ubuntu я постоянно воспроизводил ошибку «Сброс соединения».

я нашел http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101

По словам пользователя на этом форуме:

Я открыл билет с Oracle, и вот что они сказали мне.

java.security.SecureRandom - это стандартный API, предоставляемый Sun. среди различные методы, предлагаемые этим классом void nextBytes (byte []) - это один. Этот метод используется для генерации случайных байтов. Oracle 11g JDBC Драйверы используют этот API для генерации случайного числа во время входа в систему. пользователей при использовании Linux возникла ошибка SQLException (исключение Io: Сброс соединения ").

Проблема в два раза

  1. JVM пытается перечислить все файлы в / tmp (или альтернативном каталоге tmp, установленном -Djava.io.tmpdir), когда SecureRandom.nextBytes (byte []) вызывается. Если количество файлов велико, метод занимает много времени. время ответа и, следовательно, тайм-аут сервера

  2. Метод void nextBytes (byte []) использует / dev / random в Linux и на некоторых машинах, у которых нет аппаратного обеспечения для генерации случайных чисел. операция замедляется до степени доведения всего процесса входа в систему к остановке. В конечном итоге пользователь сталкивается с SQLException ("Io исключение: сброс соединения ")

Пользователи, обновляющиеся до 11g, могут столкнуться с этой проблемой, если базовая ОС Linux, работающий на неисправном оборудовании.

Причина Причина этого еще точно не установлена. Это могло бы либо проблема в вашем оборудовании, либо в том, что по какой-то причине программа не может читать из dev / random

Решение Измените настройку для вашего приложения, чтобы вы добавили следующее параметр команды java:

-Djava.security.egd = файл: / DEV /../ DEV / urandom

Мы внесли это изменение в наш файл java.security, и он избавился от ошибка.

, который решил мою проблему.

6 голосов
/ 24 февраля 2010

Сообщение об ошибке «сброс соединения» обычно означает, что другая сторона прервала соединение во время попытки создать соединение (квитирование). Это имеет много возможных причин. Ошибка в драйвере JDBC, тайм-аут на стороне БД, перезапуск базы данных, из-за нехватки доступных соединений БД, плохого качества сети, плохого virusscanner / firewall / proxy и т. Д.

Поскольку это происходит периодически, ошибка в драйвере JDBC может быть в меньшей или меньшей степени исключена. Оставленные позади оставшиеся возможные причины. Предлагаю начать с просмотра логов сервера БД.

3 голосов
/ 24 февраля 2010

Сложно сказать, но если бы я проверил актуальную версию драйвера JDBC. Убедитесь, что это 11.1.0.6.

Oracle не включает версию базы данных в имя файла. Таким образом, драйвер для 11.2 - это то же имя, что и драйвер для 11.1 - ojdbc5.jar. Я бы распаковал файл jar драйвера и нашел бы файл MANIFEST.MF, он будет содержать некоторую информацию о версии. Убедитесь, что версия драйвера JDBC совпадает с версией вашей базы данных. Я подозреваю, что это может быть проблема с версией, так как нет файла jar с именем ojdbc14.jar в Oracle 11.1.0.6 download page.

Если версия совпадает - у меня нет идей :) 1007 *

2 голосов
/ 06 октября 2014

Другая причина, которая вызывала у меня эту проблему, заключалась в неправильных настройках 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
1 голос
/ 08 февраля 2018

Основная причина этой проблемы связана с версиями аутентификации пользователя. Для каждого пользователя базы данных в базе данных хранится несколько верификаторов паролей. Обычно, когда вы обновляете базу данных, в список добавляется новый верификатор пароля, более сильный. Следующий запрос показывает версии верификатора пароля, доступные для каждого пользователя. Например:

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

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

При обновлении до более нового драйвера вы можете использовать более новую версию верификатора, поскольку драйвер и сервер согласовывают максимально возможный верификатор, который будет использоваться. Эта новая версия верификатора будет более безопасной и будет включать генерацию больших случайных чисел или использование более сложных хеш-функций, которые могут объяснить, почему вы видите проблемы при установлении соединений JDBC. Как уже упоминалось в других ответах, использование /dev/urandom обычно решает эти проблемы. Вы также можете отказаться от проверки вашего пароля и заставить более новый драйвер использовать тот же самый старый верификатор пароля, который использовался вашим предыдущим драйвером. Например, если вы хотите использовать верификатор пароля 10G (только для целей тестирования), сначала нужно убедиться, что он доступен для вашего пользователя. Установите SQLNET.ALLOWED_LOGON_VERSION_SERVER=8 в sqlnet.ora на сервере. Тогда:

SQL> alter user scott identified by "tiger";

User altered.

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

Затем вы можете заставить тонкий драйвер JDBC использовать верификатор 10G, установив это свойство JDBC oracle.jdbc.thinLogonCapability="o3". Если вы столкнулись с ошибкой "ORA-28040: No matching authentication protocol", то это означает, что ваш сервер не позволяет использовать верификатор 10G. Если это так, то вам нужно снова проверить свою конфигурацию.

1 голос
/ 22 мая 2013

Просто чтобы уточнить - хотя бы из того, что мы нашли на нашей стороне! Это проблема с настройкой рандомизатора для Linux в дистрибутиве JDK - и мы нашли его в Java6, не уверенный в Java7. Синтаксис для linux для рандомизатора: file: /// dev / urandom, но запись в файле (вероятно, оставлена ​​/ скопирована из Windows) как file: / dev / urandom. Тогда Java, вероятно, вернется к значению по умолчанию, которое будет / dev / random. И который не работает на безголовой машине !!!

1 голос
/ 23 ноября 2010

Я нашел эту ссылку для той же проблемы с 64-битной системой, драйвером jdbc 11g и сбросом соединения: http://forums.oracle.com/forums/thread.jspa?messageID=3793101

0 голосов
/ 18 сентября 2016

за ошибку https://bugs.openjdk.java.net/browse/JDK-6202721

Java не будет обрабатывать -Djava.security.egd = файл: / dev / urandom

Это должно быть -Djava.security.egd = file: / dev /./ urandom

0 голосов
/ 25 июля 2015

-Djava.security.egd = file: / dev /./ urandom должен быть правильным! not -Djava.security.egd = file: / dev /../ dev / urandom или -Djava.security.egd = file: /// dev / urandom

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...