Обсуждение: BUG #5127: AbstractJdbc2Connection#doRollback should throws Exception if connection is closed
The following bug has been logged online: Bug reference: 5127 Logged by: Email address: taktos@gmail.com PostgreSQL version: 8.3.7 Operating system: CentOS 5.1 Description: AbstractJdbc2Connection#doRollback should throws Exception if connection is closed Details: If PostgreSQL server is restarted, old Connection pooled in Application server's ConnectionPool cannot connect to DB. That's OK. But, I can call rollback() on old Connection and it throws no exception. (I've set autocommit to false and ProtocolConnection#getTransactionState returns 0) It's fault. Rollback() should fail (throw exception) because JDBC connection could not execute rollback.
Re: BUG #5127: AbstractJdbc2Connection#doRollback should throws Exception if connection is closed
От
"Kevin Grittner"
Дата:
<taktos@gmail.com> wrote: > If PostgreSQL server is restarted, old Connection pooled in > Application server's ConnectionPool cannot connect to DB. > That's OK. > But, I can call rollback() on old Connection and it throws no > exception. Hmmm.... What problem are you having? The transaction would have been rolled back when the server was restarted (or if the connection was broken). What benefit would you get from the exception you suggest? -Kevin
Re: BUG #5127: AbstractJdbc2Connection#doRollback should throws Exception if connection is closed
От
"Kevin Grittner"
Дата:
takiguchi <taktos@gmail.com> wrote: > This is a problem of connection pooling, not of transaction. > > public void testConnection() { > Connection con = dataSource.getConnection(); // get a connection > from pool (If DB server restarted, invalid connection will be > returned) > boolean valid = true; > try { > // execute some DMLs... > con.commit(); > } catch (SQLException e) { > try { > con.rollback(); > } catch (SQLException e) { > valid = false; // UNREACHABLE > } > } finally { > if (valid) { > con.close(); // Connection#close() doesn't close > connection in reality in connection pooling mechanism. It simply > returns the connection to pool. > } > } > } > > Because rollback() throws no exception when physical connection has > been closed, I cannot know whether rollback was successfully > completed. > In general, if rollback() throws NO exception, it must be a success. > (Success means rollback process is executed, and ended successfully. > This represents that connection could access to server.) > > I think if physical connection has closed, Connection's method > should fail and throws Exception. That's sort of an odd construct, but I see your point. Checking the javadocs, I see that they very explicitly support your position. http://java.sun.com/javase/6/docs/api/java/sql/Connection.html#rollback%28%29 | SQLException - if a database access error occurs, this method is | called while participating in a distributed transaction, this method | is called on a closed connection or this Connection object is in | auto-commit mode This is indeed a bug. No doubt about it. Since it is a JDBC driver bug, it might be best to post to that list, with a reference back to this thread. Do you want to put together a JDBC driver patch, or should I? -Kevin
Re: BUG #5127: AbstractJdbc2Connection#doRollback should throws Exception if connection is closed
От
"Kevin Grittner"
Дата:
takiguchi <taktos@gmail.com> wrote: > public void testConnection() { > Connection con = dataSource.getConnection(); // get a connection > from pool (If DB server restarted, invalid connection will be > returned) > boolean valid = true; > try { > // execute some DMLs... > con.commit(); > } catch (SQLException e) { > try { > con.rollback(); > } catch (SQLException e) { > valid = false; // UNREACHABLE > } > } finally { > if (valid) { > con.close(); // Connection#close() doesn't close > connection in reality in connection pooling mechanism. It simply > returns the connection to pool. > } > } > } I'm looking at the JDBC driver, and so far I can't see why a rollback attempt wouldn't generate a SQLException when the commit attempt did so for a broken connection. Is it possible that you have autoCommit set to true? The driver is currently skipping the commit or rollback attempts when that is true, which is improper; but I'm not sure you're going to be very happy with the above code if we make it behave like the Sun javadocs require, either. With autoCommit set to true, *any* commit or rollback attempt should throw an exception, so in that case the above code would never return a connection to the pool, nor would it close the connection properly. This makes me concerned that fixing the bug in the JDBC driver could expose serious bugs in application code, and break things which are currently working, for some values of "working". :-( -Kevin
Hi, Kevin. Thank you for your reply. This is a problem of connection pooling, not of transaction. public void testConnection() { Connection con = dataSource.getConnection(); // get a connection from pool (If DB server restarted, invalid connection will be returned) boolean valid = true; try { // execute some DMLs... con.commit(); } catch (SQLException e) { try { con.rollback(); } catch (SQLException e) { valid = false; // UNREACHABLE } } finally { if (valid) { con.close(); // Connection#close() doesn't close connection in reality in connection pooling mechanism. It simply returns the connection to pool. } } } Because rollback() throws no exception when physical connection has been closed, I cannot know whether rollback was successfully completed. In general, if rollback() throws NO exception, it must be a success. (Success means rollback process is executed, and ended successfully. This represents that connection could access to server.) I think if physical connection has closed, Connection's method should fail and throws Exception. Other JDBC Drivers (like Oracle) throws Exception when Connection's method (rollback, prepareStatement, etc.) was called and physical connection had been closed. Sincerely, takiguchi
> Is it possible that you have autoCommit set to true? No, it is impossible as you know. Sample code I wrote is just a sample. Actually I use a DI container (Seasar, it is a popular DI container in Japan), and Seasar provides DBCP implementation. > This makes me concerned that fixing the bug in the JDBC driver could > expose serious bugs in application code, and break things which are > currently working, for some values of "working". :-( Indeed. But on the other hand, it is serious problem that PostgreSQL doesn't behave like other JDBC drivers. On a related note, JDK 6's JDBC is based on JDBC 4.0 spec. I see JDK 5's, and I found a bit of difference to 6's. http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Connection.html#rollback() | SQLException - if a database access error occurs or this Connection | object is in auto-commit mode There is no explicit spec about use of closed connection! Because PostgreSQL's JDBC Driver is based on JDBC 3 specification, it maybe that this is not a bug. I'm still thinking that this is driver's bug. But if PostgreSQL team decides that it's not a bug and won't fix, I accept the inevitable. And I wait for a version compliant for JDBC 4.0. Regards, takiguchi