This week's book giveaway is in the Cloud forum.
We're giving away four copies of The Business Blockchain and have William Mougayar on-line!
See this thread for details.
Win a copy of The Business Blockchain this week in the Cloud forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

what happens if rollback is not called?

 
Kelly Dolan
Ranch Hand
Posts: 109
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In code I came across, I see pretty standard stuff:



I have 2 questions:

1) Scenario 1:
* on call of the local method, create ut as a local method variable
* ut.begin()
* an exception is thrown either by the do lots of stuff or commit line
* the exception is not caught and therefore rollback is not called
* ut goes out of scope and is destroyed

What is the state of the database? Since the changes were not committed or were not successfully committed, does the database reflect the state before all changes were made? Or is the database in an unstable state?

2) Scenario 2 (note: assume only one thread):
* ut is a data member and created in the constructor
* on call of the local method, ut.begin() is called
* an exception is thrown either by the do lots of stuff or commit line
* the exception is not caught and therefore rollback is not called
* on call of the local method again, ut.begin() is called
* etc.

What is the state of the database? In this case, we may have ut.begin(), do stuff fails, ut.begin() or ut.begin(), do stuff, ut.commit()-fails, ut.begin() if the catch block is not executed.

Obviously, the code needs improved but I'd like to understand the impact so that we make the correct changes (e.g., catch Exception vs. catch Throwable vs. rollback in finally block). There is much debate over the choices but that is not what I intend for this post. Also, if there is a better forum for this post, please feel free to move.

Thanks,
Kelly
 
K. Tsang
Bartender
Posts: 3583
16
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I doubt your described scenarios will rarely occur.

First by default, the connection commits automatically. In your program, you need to explicitly set the connection's auto commit to false before using commit and rollback. If auto commit is true (default), and commit or rollback is called, SQLException is thrown (stated in the API).

Now about the exception. SQLException is subclass of Exception and is a checked (not runtime) exception. The only situation I can think of is you don't catch SQLException or Exception or Throwable but some irrelevant exception like IOException (assuming your code is not IO related). But again your IDE will warn you about this.
 
Kelly Dolan
Ranch Hand
Posts: 109
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree the described scenarios will rarely occur but we're encountering a bug that is being elusive, someone noticed this code and now there are some saying this may be problem. While it may be true, it has not yet been proven and I'm trying to avoid premature and improper code changes made based on theory.

I left out a lot of detail ...
(a) the db connection auto-commit is set to false
(b) the catch block does not necessarily catch all possible exceptions (checked, unchecked or errors); note: the IDE will not complain about checked exceptions if the method declares them in its signature

So my questions remain...I'm still looking to understand what occurs if ut.rollback is not called in the 2 different scenarios.

Thanks!



 
K. Tsang
Bartender
Posts: 3583
16
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Kelly Dolan wrote:(b) the catch block does not necessarily catch all possible exceptions (checked, unchecked or errors); note: the IDE will not complain about checked exceptions if the method declares them in its signature


Somewhere in your code will (should) catch these exceptions and handle them. If not it's just simply bad programming practice. Only checked exceptions should be defined in method signatures.
 
Kelly Dolan
Ranch Hand
Posts: 109
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I respectfully thank you for your response. I do not necessary disagree w/ your feedback but that is not the subject of this post. My post is trying to get at what occurs given the code snippet as it is.
 
Martin Vajsar
Sheriff
Posts: 3752
62
Chrome Netbeans IDE Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There might be other things beyond autocommit that aren't expressed in your scenarios. But assuming the autocommit is off and there isn't any error handling up the call stack, this is what I think will happen. (You should also specify what is ut. I'm assuming ut is a Connection, but Connection doesn't have a method for starting a transaction. I'm therefore ignoring the ut.begin() calls in your scenarios.)

Scenario 1:
After ut goes out of scope, the connection is not closed. So you've got a connection leak. The leaked connection still has an active transaction, and any locks acquired in that transaction in the database remain until the connection is closed or transaction is rolled back. The connection can be closed in several ways:
  • the Connection's finalize method closes it,
  • the connection is timed out either in the database or in a connection pool,
  • a database administrator kills it, because it hogs important DB resources.

  • After the connection is closed, the failed transaction is rolled back and associated locks are freed.

    The transaction might also be rolled back automatically. Some databases (Oracle, for example) detect deadlocks and when one occurs, they select one of the transactions and roll it back to resolve the deadlock. It is not guaranteed that it will be the transaction in your leaked connection, the DB might choose another connection which is still being used to roll back its transaction. Some databases might limit maximum duration of a transaction and roll it back too. And if the connection was participating in a distributed transaction, I believe it could also be rolled back under some circumstances.

    This is probably not a complete list. There might be other ways in which the connection could be closed or the transaction rolled back. But until it happens for whatever reason, the transaction remains active.

    Scenario 2:
    This scenario, as described, probably assumes that ut is a static variable (otherwise it would go out of scope after the exception - which is uncaught - occurred). Generally, until you commit, you're in the same transaction in the connection. Some errors might also cause rollbacks, but most probably don't. So in your scenario, the next call of the local method performs the database operations in the same transaction in which the error occurred. Any changes made by the failed method call are still there and if the second method call succeeds and commits, both operations - the first one which completed only partially and the second one which completed successfully - will be persisted in the database. It is a nasty bug which would be hard to properly identify. (Of course, the failed operation might cause the subsequent operation to fail as well, but this is the good outcome.)
     
    Kelly Dolan
    Ranch Hand
    Posts: 109
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sorry, ut is a javax.transaction.UserTransaction. The DB connections are obtained and used properly (e.g., closed in finally block) in the // do stuff logic. The DB connection commit and rollback methods are not called by our code directly. Rather they are invoked by the transaction on its commit/rollback.
     
    Martin Vajsar
    Sheriff
    Posts: 3752
    62
    Chrome Netbeans IDE Oracle
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I'm not acquainted with JTA well enough. The only thing I know for sure is that when a database connection is physically closed, any pending transaction is rolled back. Well implemented connection pools should also rollback a transaction when you return a connection with active transaction to the pool by calling Connection.close(), but there might be poor connection pool implementations around that wouldn't ensure it.
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic