Reputation: 123
I have the following two queries resulting in a deadlock. But do not know why Oracle tries to make an SSX Table lock in this scenario.
All test samples tried to replicate the problem, do only row locking.
------------Blocker(s)----------- ------------Waiter(s)------------
Resource Name process session holds waits serial process session holds waits serial
TM-000386AF-00000000-00000000-00000000 101 298 SX SSX 65474 27 646 SX SSX 21533
TM-000386AF-00000000-00000000-00000000 27 646 SX SSX 21533 101 298 SX SSX 65474
Query:
DELETE FROM VERSANDPALETTE V WHERE V.ID IN (SELECT COLUMN_VALUE FROM TABLE(:B1 ))
----- Information for the OTHER waiting sessions -----
Session 646:
DELETE FROM VERSANDPALETTE WHERE ID IN (SELECT * FROM TABLE(:B1 )) AND ID NOT IN (SELECT * FROM TABLE(:B2 ))
I would expect, that the independent rowsets are deleted and no table lock is created.
Does someone has a hint on why that could happen?
EDIT 2: (Simplified Version of the question, 2 min to replicate)
Thanks for your help!
I used this code to test it further:
-- setup
create table p ( x int primary key );
create table c ( x references p );
insert into p select rownum from dual connect by level <= 10;
insert into c select * from p;
commit;
-- 2 session test
-- session 1
update c set x = 2 where x = 1;
-- session 2
update c set x = 4 where x = 3;
delete from p where x = 3;
-- session 1
delete from p where x = 1;
-- deadlock is happening now
-- rollback both sessions
This leads to a deadlock as expected, because there is no index on the child table fk. (as you pointed out to me)
What confuses me is, when only one session is used that there are only locked_mode 3 v$locked_object open. There should be a locked_mode 5 row somewhere.
-- 1 session test
update c set x = 2 where x = 1;
update c set x = 4 where x = 3;
delete from p where x = 3;
delete from p where x = 1;
select
c.owner,
c.object_name,
c.object_type,
b.sid,
b.serial#,
b.status,
b.osuser,
b.machine,
a.locked_mode
from
v$locked_object a ,
v$session b,
dba_objects c
where
b.sid = a.session_id
and
a.object_id = c.object_id;
-- no locked_mode 5 entries...
-- rollback the session
Adding an index resolves the problem:
CREATE INDEX c_index ON c(x);
-- 2 session test
-- session 1
update c set x = 2 where x = 1;
-- session 2
update c set x = 4 where x = 3;
delete from p where x = 3;
-- session 1
delete from p where x = 1;
-- deadlock is not happening :)
So I guess there is some lock escalation going on? Because the single session test does not aquire the same table lock.
Upvotes: 1
Views: 785
Reputation: 15094
As krokodilko says, do you have any dependent tables with a foreign key and the on delete cascade
option? The SSX lock is to prevent inserts to the child table for a parent table that has had a row deleted.
See: https://asktom.oracle.com/pls/apex/asktom.search?tag=deadlock-on-two-delete-statements
Upvotes: 2