У меня есть два следующих запроса, которые приводят к тупику.Но не знаю, почему Oracle пытается установить блокировку таблицы SSX в этом сценарии.
Все тестовые примеры пытались воспроизвести проблему, делают только блокировку строк.
------------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 ))
Я ожидаю,что независимые наборы строк удаляются и таблица не блокируется.
Есть ли у кого-нибудь подсказка о том, почему это может произойти?
РЕДАКТИРОВАТЬ 2: (Упрощенная версия вопроса, 2минута для репликации)
Спасибо за вашу помощь!
Я использовал этот код для дальнейшего тестирования:
-- 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
Это приводит к тупикукак и ожидалось, потому что нет индекса на дочерней таблице fk.(как вы указали мне)
Что меня смущает, так это то, что когда используется только одна сессия, открываются только locked_mode 3 v $ locked_object.Где-то должна быть строка locked_mode 5.
-- 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
Добавление индекса решает проблему:
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 :)
Итак, я предполагаю, что происходит некоторое повышение блокировки?Потому что тест с одним сеансом не требует той же блокировки таблицы.