Skip to Main Content
  • Questions
  • Deadlock during delete from parent and insert on child

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Alex.

Asked: August 24, 2016 - 9:05 am UTC

Last updated: August 24, 2016 - 4:03 pm UTC

Version: 11.2.0.1

Viewed 1000+ times

You Asked

Hello Team! :)

I get the "ORA-00060: deadlock detected while waiting for resource" in the following case:

Session1:

--DDL
create table t1(pk number(11) primary key, col1 number(11));

create table t2(pk number(11) primary key, t1_ref_key number(11), col1 number(11),
constraint fk_t2__t1_pk foreign key (t1_ref_key) references t1(pk) on delete cascade);

create table t3(pk number(11) primary key, t1_ref_key number(11), col1 number(11),
constraint fk_t3__t1_pk foreign key (t1_ref_key) references t1(pk) on delete cascade);

create index t2_ref_key on t2(t1_ref_key);

create index t3_ref_key on t3(t1_ref_key);

--DML

insert into t1(pk, col1) values (1, 123);

COMMIT; --commit here

insert into t2(pk, t1_ref_key, col1) values (1, 1, 123);

--no commit yet


Now in Session 2 the following statement is executed:

delete from t1 where pk=1;

--Session 2 waits here



Now again in Session 1:

insert into t3(pk, t1_ref_key, col1) values (1, 1, 123);

--no commit yet


In this moment the Session 2 gets "ORA-00060 deadlock detected ...". Could you please say, why this is happening and how I as a developer can avoid this?

Regards,
Alex

and Chris said...

When you insert a row into T2 Oracle blocks deletes to the parent row in T1. Otherwise it can't validate the FK.

When you delete a row from T1 Oracle blocks inserts of potential children of this. Again, this is to ensure it can validate the FK.

So in your example you have:

Session 1 preventing the delete from the parent.
Session 2 preventing the insert into the children.

Deadlock!

How can you avoid this?

Stop deleting from T1! ;)

But I'm guessing that's not an option. You can avoid the deadlock by issuing:

select * from t1 where pk = :x for update;


Before inserting rows into the child tables (T2 & T3).

If the delete starts first, the select will be blocked. When the delete commits, the inserts will go ahead and the FK validation will fail.

If the select for update starts first, the delete will have to wait for this to commit. Once you commit the inserts, the delete will go ahead. The side-effect of this is you'll end up deleting rows you just inserted!

Rating

  (1 rating)

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

Comments

Thanks for the answer!

Alex, August 24, 2016 - 8:31 pm UTC

Thanks for the answer, Chris!

In my case the Session 1 (which inserts into T2 and T3) is actially a long running reporting process (T1 is a report definition header table, T2 is some precalculation table, T3 is a report result table). Session 2 is a user session which wants to update report defintion (unfortunately this is a update-by-delete procedure). And what I wanted to avoid is locking of the report definiton header (row in T1) to let other sessions to mark report as 'invalidated' quickly, when some dependency data was modified... But if there is no other possibility, then I still find you answer useful, even if it is not applicable in my case. :)

Many Thanks and Best Regards,
Alex