Базы данных Oracle - статьи



              

Механизм взаимоблокировки - часть 3


SYSTEM@XE> SELECT * FROM v$lock WHERE sid IN (24, 28) AND type = 'TX';   ADDR     KADDR    SID TYPE ID1    ID2 LMODE REQUEST CTIME BLOCK -------- -------- --- ---- ------ --- ----- ------- ----- ----- 2A201720 2A201734 28  TX   327718 163 0     6       1074  0    296EE5D8 296EE6F4 28  TX   262166 169 6     0       7048  0    296FA680 296FA79C 24  TX   327718 163 6     0       6817  1      Выбрано: 3 строки

Как мы видим, в представлении появилась новая строка о TX-блокировке со значением 6 в поле REQUEST.  Данное значение означает, что сеанс 28 запросил установку TX-блокировки строки  в исключительном режиме. При этом значения столбцов ID1 и ID2 этого запроса содержат идентификатор транзакции сеанса 24. Это свидетельствует о том, что первый сеанс ожидает освобождения строки, захваченной транзакцией именно второго сеанса.

Итак, на данный момент мы имеем классическую картину ожидания. Но что произойдет, если мы изменим во втором сеансе первую строку? Ведь она уже захвачена первым сеансом:

ZH@XE(24)> UPDATE t1 SET c2 = 'Строка1' WHERE c1 = 1;

Ожидание…

Возникает ожидание, и мы становимся свидетелями типичного случая взаимного блокирования. Второй сеанс ожидает освобождения первой строки, заблокированной в результате, начатой транзакции первого сеанса. В то же время первый сеанс ожидает освобождение второй строки, заблокированной транзакцией второго сеанса.  Такое ожидание могло бы продолжаться вечно, но, как отмечали ранее, Oracle сам определяет возникновение подобных тупиковых ситуаций в течение примерно трёх секунд. В нашем случае он просто отменит выполнение последнего оператора UPDATE в первом сеансе и сгенерирует следующую ошибку:

ZH@XE(28)> UPDATE t1 SET c2 = 'Строка2' WHERE c1 = 2;   UPDATE t SET c2 = 'Строка2' WHERE c1 = 2        * Ошибка в строке 1: ORA-00060: deadlock detected while waiting for resource

Убедимся в том, что транзакции отменены не были. Для этого выполним следующий запрос:

SYSTEM@XE> SELECT s.sid, t.status, t.start_time, t.xid  FROM v$transaction t, v$session s  WHERE t.addr = s.taddr;   SID STATUS START_TIME        XID             --- ------ ----------------- ---------------- 24  ACTIVE 01/21/10 23:14:40 05002600A3000000 28  ACTIVE 01/21/10 23:10:49 04001600A9000000




Содержание  Назад  Вперед