Skip to Main Content
  • Questions
  • Timeout db statement after some time without keeping anything any locks on the database side

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Manjula.

Asked: September 08, 2016 - 5:32 am UTC

Last updated: September 08, 2016 - 12:50 pm UTC

Version: 12G

Viewed 10K+ times! This question is

You Asked

Hi Tom,

I'm using spring-jdbc(JDBCTemplate) with oracle.jdbc.pool.OracleDataSource to execute few queries(copying data from one table(table 1) to another(table 2) and deleting copied entries from table 1) within a single transaction(transactions are handled via org.springframework.jdbc.datasource.DataSourceTransactionManager). Please see below sample code block to explain my scenario

try {
<<Strat Transaction>>
jdbcTemplate.update(<<INSERT FROM TABLE 1 TO TABLE2>>)
jdbcTemplate.update(<<DELETE FROM TABLE 1>>)
<<Commit Transaction>>
} catch(Exception e) {
<<Roll back Transaction>>
}

However, there is a possibility that my delete statement gets blocks on some other queries with row locking(which will manage by a separate module/application) I want to timeout my second statement(bold one) after some time if it cannot proceed due to locks in the database. So I have used "oracle.jdbc.ReadTimeout" property to fulfill my requirement. It worked as expected and timed out after the ReadTimeout value with a Socket Read Timeout IOException which is completely okay.

My problem is after the Socket Readtimeout exception my delete statement doesn't get cleared from the database side and it will be there as an active statement which waits for a row lock. I believe this is because I'm already inside a transaction and Oracle waits until it receives either commit or rollback command from the client side to complete the transaction, but I'm not sure how to return after the timeout without keeping any garbage that I have created on the database side.

Can you please explain how should I configure/proceed to fulfil my requirement? Basically, I want to know how to avoid keeping my client waiting indefinitely for a lock and get timed out after some time without keeping any stale locks at the database side.

Your suggestion will be highly appreciated. (Sorry for the lengthy explanation, I wanted to try my best to cover all the required information to understand my question)

Thanks,
Manjula

and Connor said...

Lock the table before you commence activity, eg

--
-- Session 1
--
SQL> update t set x = 1;

1 row updated.


Now Session 2 (your application) shouldnt do anything until it knows it can get a consistent view of things (otherwise it might delete MORE than it inserted). So we do this:

lock table t in exclusive mode wait 10;
insert into t1 select * from t;
delete from t;

In the example here, let's see what happens (because the update above has NOT yet committed):

SQL> lock table t in exclusive mode wait 10;
lock table t in exclusive mode wait 10
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


So I tried for 10 seconds, but didnt start because there was an outstanding transaction.

Hope this helps.


Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks a lot for the quick response

Manjula Piyumal, September 08, 2016 - 7:07 am UTC

Thanks a lot for your quick response and suggestions. I'm thinking whether this will suit my requirement since I'm doing this data moving task in three pairs of tables and I want them to proceed with a single transaction. So if I have to go with your suggestion, I have to lock all three tables before proceeding which may lead to a complex logic :-(

Could you please help me to understand whether there is a way to return without keeping any locks at the server side. The problem in even with your suggestion what will happen if I cannot complete the task after acquiring the exclusive lock on the table? Let's say that I have a lot of rows to move and I cannot complete the data movement task before readtimeout value(may be due to other external facts). As I have observed, the behaviour will be my client will be returned with a socket read time out exception and my delete statement will the there forever since I couldn't either commit or rollback my transaction because my connection is already closed at the driver level in socket read timeouts. I'm not sure whether I have missed something here, so your help and suggestions are really appreciated. I want to guaranty that I won't keep any stale locks if I couldn't complete my transaction due to network level failures or any failures that I will hit at the client side and database server will rollback my locks if my client is not connected any longer

Thanks,
Manjula
Connor McDonald
September 08, 2016 - 12:50 pm UTC

You are *always* holding locks on the server side. The moment you update 1 row you have taken out locks. And if your client simply "forgets" about the database when it times out, then no matter what you do, you are doing to have locks left hanging around.

You could look at resource manager or profiles to try clean up the mess after a certain time...but basically, if your client doesnt behave well with the database, then you're going to have troubles.