Technical Blog Post
Why is the transaction taking a long time to rollback after a transaction timeout in WebSphere Application Server?
The transaction timeout value can be set in the application component or in the administrative console for WebSphere Application Server (WAS). If the application component does not specifically set its own transaction timeout, WAS will timeout a transaction according to the 'Total transaction lifetime timeout' property. This property is the default maximum time allotted for a transaction to complete before it is timed out. If completion processing is not started on the transaction before this timeout value is reached, it will be rolled back. By default, this property is set to 120 seconds. This value should also be lower than the 'Maximum transaction timeout' value for it to take effect. The 'Maximum transaction timeout' value is the upper transaction timeout limit for all transactions running on a particular server. This value should be greater than or equal to BOTH the application component timeout and the 'Total transaction lifetime timeout'. If it is not, transactions will timeout according to this value which could cause them to timeout earlier than expected. By default, this property is set to 300 seconds. If you set the 'Total transaction lifetime timeout' value to 0 seconds, this property will not apply, and the 'Maximum transaction timeout' value will be used if the application component does not set a transaction timeout.
When a transaction timeout is reached, the transaction will be marked for rollback. Once the next transaction boundary is reached, the transaction will then start the rollback process. The next transaction boundary can be reached by an entry or exit to an EJB method, by enlisting other resources, etc. The time difference between the transaction timing out and the transaction rolling back is directly related to how quickly the transaction thread of control hits a transaction boundary after a timeout.
Because the rollback process is not started until the next transaction boundary is reached, it may take much longer than a few seconds for the transaction to completely rollback after the timeout has occurred if the next transaction boundary is not immediately reached. This can occur oftentimes if there are many queries and updates being made to the database in a single method. One way to resolve this would be to loop the query in one method that calls another EJB method that does the actual update. This will allow a transaction boundary (EJB method) to be reached quicker which will start the rollback process sooner. Modifying the application itself to incorporate a transaction boundary will allow the transaction rollback to complete more quickly once the transaction timeout occurs.
The transaction cannot start the rollback process immediately after the transaction timeout is reached due to a Java™ programming language limitation that does not allow interruption of a thread executing application code. A thread can only be interrupted when it is waiting, joining, or sleeping. Because of this, application processing can only be cut short when container code is run like an EJB method being called. This means that the transaction thread cannot be interrupted until a transaction boundary is reached.
Setting a query timeout value can often times allow the transaction rollback to occur quicker. The query timeout can be set in the application component or on the data source used by an application. This property allows the SQL statement to be interrupted if it does not complete within the allotted time. If the syncQueryTimeoutWithTransactionTimeout property is set on the data source, the query timeout will be synchronized with the transaction timeout value. Every time a new SQL statement is made within the transaction, the time remaining until the transaction timeout is reached will be used as the default query timeout for the SQL statement. A SQLTimeoutException will then be thrown if the SQL statement does not complete in this allotted time or if the time remaining is less than or equal to 0. The application component should catch this SQLTimeoutException, give up on retrying the SQL statement, allow the thread to finish running the application code, and then return the thread to the container. Once the thread is returned to the container, transaction rollback processing will begin. Using this property to allow transaction rollback to occur quicker may also require application changes to catch and handle the SQLTimeoutException as mentioned above. Keep in mind that the SQLTimeoutException is a subclass of SQLException and not RuntimeException.
Information on how to set the properties mentioned in this post can be found here: