У нас есть приложение для составления отчетов, которое может выполнять длинные запросы. Пользователь может отменить текущий отчет, нажав кнопку. Это вызывает метод, который останавливает поток отчетов и закрывает его соединение JDBC.
Проблема, с которой мы сталкиваемся, заключается в том, что соединение JDBC возвращается в пул Tomcat, но оно все еще используется. Поэтому, когда другой поток получает это соединение и пытается его использовать, выполнение в драйвере Oracle блокируется оставленным оператором.
Кажется, что исправлением было бы сначала вызвать метод Statement.cancel (), но некоторые указали (http://stackoverflow.com/a/659063/603516), что этот метод может не иметь немедленного эффекта.
Так, каков правильный подход? Могу ли я закрыть соединение, не возвращая его в пул? Должен ли я оставить его открытым? Я знаю, что есть некоторые настройки тайм-аута, которые я мог бы установить для соединения, но, поскольку это приложение для составления отчетов, запросы могут выполняться в течение нескольких часов, и я не чувствую себя комфортно, устанавливая какой-либо таймаут.
Может быть, один из вариантов - установить validationQueryTimeout? Но что, если соединение не проверяется перед каждым использованием?
> "Report_Worker-26" Id=104 in RUNNABLE (running in native)
> at java.net.SocketInputStream.socketRead0(Native Method)
> at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
> at java.net.SocketInputStream.read(SocketInputStream.java:170)
> at java.net.SocketInputStream.read(SocketInputStream.java:141)
> at oracle.net.ns.Packet.receive(Packet.java:311)
> at oracle.net.ns.DataPacket.receive(DataPacket.java:105)
> at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:305)
> at oracle.net.ns.NetInputStream.read(NetInputStream.java:249)
> at oracle.net.ns.NetInputStream.read(NetInputStream.java:171)
> at oracle.net.ns.NetInputStream.read(NetInputStream.java:89)
> at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123)
> at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79)
> at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:426)
> at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:390)
> at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249)
> at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:566)
> at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:215)
> at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:58)
> at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:776)
> at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:897)
> at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1034)
> at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3820)
> at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3867)
> - locked oracle.jdbc.driver.T4CConnection@60e36e18
> at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1502)
> ...
>
> "http-bio-9050-exec-17" Id=205 in BLOCKED on
> lock=oracle.jdbc.driver.T4CConnection@60e36e18
> owned by Report_Worker-26 Id=104
> at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:3878)
> at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:453)
> at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:394)
> at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:775)
> at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:619)
> at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:188)
> at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:128)