Bug #63947 | Rollback hangs if OutOfMemoryException was thrown when reading the query results | ||
---|---|---|---|
Submitted: | 6 Jan 2012 10:01 | Modified: | 19 Mar 2014 14:10 |
Reporter: | Topi Nieminen | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | Connector / J | Severity: | S3 (Non-critical) |
Version: | 5.1.18 | OS: | Any |
Assigned to: | Filipe Silva | CPU Architecture: | Any |
Tags: | Contribution, jdbc |
[6 Jan 2012 10:01]
Topi Nieminen
[26 Jan 2012 19:21]
Sveta Smirnova
Thank you for the report. Problem is repeatable for me with 1 exception: connection still exists: [2012-01-26 21:15:01,084] INFO 681[main] - bug63947.run(bug63947.java:62) - connection closed ? false [2012-01-26 21:15:01,085] INFO 682[main] - bug63947.run(bug63947.java:64) - rolling back... ... *************************** 13. row *************************** event_time: 2012-01-26 21:15:00 user_host: root[root] @ localhost [127.0.0.1] thread_id: 3 server_id: 1 command_type: Query argument: select * from test r1, test r2, test r3, test r4, test r5, test r6, test r7, test r8, test r9, test r10, test r11, test r12, test r13, test r14, test r15 *************************** 14. row *************************** event_time: 2012-01-26 21:15:01 user_host: root[root] @ localhost [127.0.0.1] thread_id: 3 server_id: 1 command_type: Query argument: rollback So it is surely not closed and c/J confirms it. Please turn on general query log and check if this is your case too.
[26 Jan 2012 20:36]
Topi Nieminen
I'm curious to know how the connection goes through cleanup() and stays open in your case. Which location does OutOfMemoryError originate from in your test case? According my test program output connection is closed: 2012-01-26 22:19:59,896 [main] INFO test.TestOOM - -- select * from test r1, test r2, test r3, test r4, test r5, test r6, test r7, test r8, test r9, test r10, test r11, test r12, test r13, test r14, test r15 2012-01-26 22:19:59,896 [main] INFO test.TestOOM - executing query... com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection closed forcibly due to memory allocation failure. Transaction resolution unknown. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2674) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:842) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:681) at test.TestOOM.execute(TestOOM.java:94) at test.TestOOM.run(TestOOM.java:69) at test.TestOOM.main(TestOOM.java:20) Caused by: java.lang.OutOfMemoryError: Java heap space at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:1657) at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1434) at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:2936) at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:477) at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:2631) at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:1800) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2221) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) ... 6 more 2012-01-26 22:20:00,460 [main] INFO test.TestOOM - connection closed ? true 2012-01-26 22:20:00,460 [main] INFO test.TestOOM - rolling back... com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927) at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1205) at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1197) at com.mysql.jdbc.ConnectionImpl.rollback(ConnectionImpl.java:4705) at test.TestOOM.run(TestOOM.java:74) at test.TestOOM.main(TestOOM.java:20) Caused by: java.lang.OutOfMemoryError: Java heap space at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:1657) at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1434) at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:2936) at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:477) at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:2631) at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:1800) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2221) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:842) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:681) at test.TestOOM.execute(TestOOM.java:94) at test.TestOOM.run(TestOOM.java:69) ... 1 more
[28 Jan 2012 0:40]
Sveta Smirnova
Thank you for the feedback. Verified as described. Error in my environment: There was 1 error: 1) testBug63947(bug63947)com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 120 milliseconds ago. The last packet sent successfully to the server was 120 milliseconds ago. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3102) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:842) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:681) at bug63947.testBug63947(bug63947.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at bug63947.main(bug63947.java:12) Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(Unknown Source) at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114) at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161) at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189) at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002) ... 26 more This is from test case made for c/J testsuite. Your code printed data similar to yours
[28 Jan 2012 0:40]
Sveta Smirnova
test case for c/J testsuite
Attachment: bug63947.java (text/x-java), 889 bytes.
[28 Jan 2012 1:13]
Mark Matthews
Given how Java handles OOM, there's not a whole lot that can be done when this condition happens. We can maybe have the driver try to forcibly close the socket, which will cause MySQL to rollback any pending transaction, but there is no guarantee that this can happen in a normal way because any allocation of memory required to close the socket may fail (because the VM is out of memory), and it may fail in code that is not under the driver's control (i.e. java.net, java.lang). If anything the solution proposed here should *not* throw SQLException, it should not try and allocate any memory, and it should re-throw the OOM error as errors should be handled differently than checked exceptions. Java applications should generally treat OOM as a fatal error, and terminate the JVM, because no *known* progress can be made once this condition happens.
[30 Jan 2012 8:36]
Tonci Grgin
Thank you Sveta and Mark.
[12 Mar 2014 13:21]
Alexander Soklakov
Marked as Won't fix until we realize that something could be done.
[19 Mar 2014 14:10]
Alexander Soklakov
It's decided to leave it in Verified state.