Смоделируем следующую ситуацию. Создадим процедуру p1 с единственной командой, которая будет обновлять нужную нам строку таблицы t1 в зависимости от входных параметров:
SQL> CREATE PROCEDURE p1(v1 in integer, v2 in VARCHAR2) 2> AS 3> BEGIN 4> UPDATE t1 SET c2 = v2 WHERE c1 = v1; 5> END; Процедура изменена
Образуем два сеанса. В первом сеансе изменим первую строку:
ZH@XE(31)> EXECUTE p1(1, 'Строка1'); PL/SQL procedure successfully completed
Во втором сеансе изменим вторую строку:
ZH@XE(23)> EXECUTE p1(2, 'Строка2'); PL/SQL procedure successfully completed
Вернёмся в первый сеанс и изменим вторую строку:
ZH@XE(31)> EXECUTE p1(2, 'Строка2');
Ожидание…
Возникло ожидание. И это естественно, ведь мы следуем по пути первого сценария образования взаимной блокировки. Единственное отличие для нашего случая, это только то, что SQL-команды здесь спрятаны в PL/SQL процедуре. Поэтому, если дальше следовать сценарию, выполнение следующей команды, изменяющей первую строку, должно привести к взаимному блокированию:
ZH@XE(23)> EXECUTE p1(1, 'Строка1');
Ожидание…
Так и есть, в первом сеансе происходит ошибка:
ZH@XE(31)> EXECUTE p1(2, 'Строка2'); BEGIN * Ошибка в строке 1: ORA-00060: deadlock detected while waiting for resource ORA-06512: at "ZH.P1", line 4 ORA-06512: at line 2
Возникшая взаимная блокировка подобна самому первому случаю, который мы рассматривали в самом начале статьи. Первый сеанс установил TX-блокировку в монопольном режиме на первую строку и ожидает установки такой же блокировки на вторую строку. Второй сеанс, наоборот, установил TX-блокировку в монопольном режиме на вторую строку и ожидает установки такой же на первую строку. Всё, как при обычном сценарии с SQL-командами.
Рассмотрим теперь содержимое трассировочного файла взаимной блокировки. Есть ли здесь какие-либо изменения? Первая секция содержит отменённый в результате ошибки оператор первого сеанса:
Current SQL statement for this session: UPDATE T1 SET C2 = :B2 WHERE C1 = :B1