Oracle JDBC DriverManager.getConnection() зависает

У нас есть несколько серверов, на каждом из которых работает база данных Oracle 11g Release 11.2.0.1.0 — 64bit. Подключаемся через JDBC вот так:

public Connection createConnection(String drvClass, String connURL, String user, String pass)
        throws ClassNotFoundException, SQLException {
    Class.forName(drvClass);
    Connection conn = DriverManager.getConnection(connURL, user, pass);
    for (SQLWarning warn = conn.getWarnings(); warn != null; warn = warn.getNextWarning()) {
        System.out.println("SQL Warning:");
        System.out.println("State  : " + warn.getSQLState());
        System.out.println("Message: " + warn.getMessage());
        System.out.println("Error  : " + warn.getErrorCode());
    }
    return conn;
}

drvClass будет oracle.jdbc.OracleDriver. Программа, которая пытается подключиться, запускается на каждом сервере. База данных доступна из других программ с точно такими же свойствами соединения.

Также можно запустить эту программу на другом сервере и позволить ей подключиться к проблемной базе данных. Он может установить соединение. Программа не работает, если она запущена на сервере локально. Мы пробовали и IP, и имя сервера.

На одном сервере код висит на DriverManager.getConnection() и не могу понять почему. Кто-нибудь знает, что может быть причиной этого?

В логах БД нет об этом записи.

Stacktrace блокирующего потока:

"pool-27-thread-1" - Thread t@1483
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at oracle.net.ns.Packet.receive(Packet.java:239)
at oracle.net.ns.NSProtocol.connect(NSProtocol.java:255)
at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:973)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:291)
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(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at com.companyname.DBConnectionInternal.DBConnection.createConnection(DBConnection.java:19)
at com.companyname.exportadapter.ExportCollector.initDatabase(ExportCollector.java:259)
at com.companyname.exportadapter.ExportCollector.run(ExportCollector.java:120)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Locked ownable synchronizers:
- locked <50be77> (a java.util.concurrent.ThreadPoolExecutor$Worker)

Если я поставлю DriverManager.setLoginTimeout(10), то получу Io exception: Socket read timed out.


person Moh-Aw    schedule 26.05.2014    source источник
comment
Сколько клиентов пытаются одновременно получить доступ к базе данных? Может быть, вы нарушили какое-либо ограничение сервера (например, максимальное количество открытых подключений)?   -  person Jorge_B    schedule 26.05.2014
comment
база данных в настоящее время имеет около 80 соединений. SELECT value FROM v$parameter WHERE name = 'sessions' возвращает 772 возможных соединения.   -  person Moh-Aw    schedule 26.05.2014
comment
Что такое Stacktrace для блокирующего потока? recv, sendv может указать вам на проблему.   -  person Grim    schedule 26.05.2014
comment
я добавил трассировку стека блокирующего потока, но ничего не могу найти   -  person Moh-Aw    schedule 26.05.2014
comment
Это приложение можно запустить с другого сервера. Он может без проблем подключиться к проблемному серверу. Но как только программное обеспечение запускается на этом сервере, соединение зависает.   -  person Moh-Aw    schedule 26.05.2014
comment
если я установил время ожидания входа в систему на 10 секунд, я получаю: Исключение Io: время ожидания чтения сокета истекло.   -  person Moh-Aw    schedule 26.05.2014


Ответы (3)


вы можете сделать некоторые ненужные соединения.

сделайте Connection класс static, всякий раз, когда вы создаете новое соединение, проверьте, что старое соединение живо или закрыто, а затем вы должны создать новое соединение, в противном случае вернуть старое соединение.

как

 if(conn!=null & !conn.isClosed()){ 
// code for create connection
}

Это также зависит от того, как настроена сторона базы данных, поэтому уточните это у администратора базы данных вашей системы.

Я хотел бы предложить использовать пул соединений.

надеюсь это поможет.

person Sanjay Rabari    schedule 26.05.2014
comment
Я думаю, мы до сих пор этого не знаем. Возможно, клиент хорошо управляет соединениями и закрывает каждое открытое соединение. Я скорее думаю, что проблема может заключаться в том, что многие клиенты одновременно открывают соединения с базой данных и достигают предела сервера - что-то, что можно решить, поместив какой-то пул соединений посередине. - person Jorge_B; 26.05.2014
comment
в момент возникновения проблемы нет открытого соединения с этим пользователем. Соединение закрывается в блоке finally (если бы оно было открыто) в вызывающем классе. - person Moh-Aw; 26.05.2014
comment
Создание статических соединений — плохая идея, на самом деле это приведет к утечкам соединений, а не к их предотвращению. Я бы предложил использовать попытку с ресурсами в сочетании с источником данных, который обеспечивает пул соединений. - person Mark Rotteveel; 26.05.2014

Вы можете включить ведение журнала отладки JDBC для драйвера ojdbc: http://docs.oracle.com/cd/B28359_01/java.111/b31224/diagnose.htm Это может дать вам некоторую информацию о том, что делает драйвер.

Вы пытались подключиться к серверу базы данных с клиентской машины по telnet (чтобы убедиться, что он доступен)?

person Rein    schedule 26.05.2014

Сервер был неправильно настроен. По какой-то причине у него был настроен виртуальный адаптер, который возвращал IP-адрес, к которому ничего не могло подключиться. Со стороны разрешение работало корректно. Не знаю, почему время ожидания никогда не истекало с неправильным IP-адресом.

person Moh-Aw    schedule 26.05.2014