简体   繁体   中英

Concurrent update and delete on one table

Using Java, Hibernate and Oracle database. I have two concurrent processes:

  1. Process1 removes some entities from table1. (multiple: delete from table1 where id =...) Done by native hibernate query.
  2. Process2 updates SAME/other entities in table1. (multiple: update table1 set name=... where id=...) Done by jpa repository delete method.

Currently sometimes exception

CannotAcquireLockException is thrown,
(SQL Error: 60, SQLState: 61000..
ORA-00060: deadlock detected while waiting for resource)

So, the question is: what is going on and how I can avoid exception? Any workaround?

IMPORTANT: In case of collisions I would be satisfied if delete succeeds and update won't do anything.

Session A waits for B, B waits for A - this is what a deadlock basically is. Nothing to wait for any more, Oracle kills either of the sessions.

Option 1

Create semaphore to effectively serialize concurrent processes.

create table my_semaphore(dummy char(1));

Session 1:

LOCK TABLE my_semaphore in exclusive mode;
UPDATE <your update here>;
COMMIT;

Session 2:

LOCK TABLE my_semaphore in exclusive mode;
DELETE <your delete here>;
COMMIT;

Option 2 Try processing rows with both statements in the same order, say by rowid or whatever.

So that session B never returns to rows held by A, if A is stuck in behind by rows locked by B. This more tricky and resource-intesive.

"locking tables doesnt look attractive at all -what the point then of having severaal processes working with database"

Obviously we want to enable concurrent processes. The trick is to design processes which can run concurrently without interfering with each other. Your architecture is failing to address this point. It should not be possible for Process B to update records which are being deleted by Process A.

This is an unfortunate side-effect of the whole web paradigm which is stateless and favours an optimistic locking strategy. Getting locks at the last possible moment "scales" but incurs the risk of deadlock.

The alternative is a pessimistic locking strategy, in which a session locks the rows it wants upfront. In Oracle we can do this with SELECT .. FOR UPDATE. This locks a subset of rows (the set defined by the WHERE clause) and not the whole table. Find out more .

So it doesn't hinder concurrent processes which operate on different subsets of data but it will prevent a second session grabbing records which are already being processed. This still results in an exception for the second session but at least that happens before the session has done any work, and provides information to re-evaluate the task (hmmm, do we want to delete these records if they're being updated?).

Hibernate supports the SELECT FOR UPDATE syntax. This StackOverflow thread discusses it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM