В этом случае нам нужно использовать for update nowait
в курсорах.
Когда следует использовать "для обновления nowait" в курсорах?
Ответ 1
Использование for update nowait
приведет к тому, что строки будут заняты и получит блокировку, пока не будет выполнен коммит или откат.
Любой другой сеанс, который пытается получить блокировку, получит сообщение об ошибке Oracle, такое как ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
, вместо того, чтобы ждать разблокировки блокировки.
Сессии1:
CURSOR abc_cur
IS
select * from dept where deptno =10 for update nowait;
Здесь строки блокируются до тех пор, пока курсор не будет закрыт или пока не будет выполнен коммит/откат. Между тем, если другой пользователь из сеанса 2 попытается получить доступ к тем же записям, это вызовет ошибку, как показано ниже:
Сессии2:
select * from dept where deptno =10 for update nowait;
Этот пользователь не может даже обновить или удалить те же записи, которые были заблокированы в первом сеансе.
ERROR at line 1:
'ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired'
Использование:
Теперь, если вы хотите выполнить некоторые манипуляции с определенными наборами записей и не хотите, чтобы другой пользователь из другого сеанса переопределял ваши данные, вы должны сначала заблокировать записи (используя for update nowait
), а затем выполнить ваши манипуляции. После того, как вы закончите с вашими манипуляциями, закройте курсор и подтвердите.
EDIT Предположим, что в строке 10 строк, и я выполняю следующий скрипт в моем сеансе 1:
declare
cursor abc is select * from temp for update nowait;
temp abc%rowtype;
begin
open abc;
-- do slow stuff here
close abc;
commit;
end;
В сеансе 2 я выполняю следующее, пока сценарий в сеансе 1 все еще выполняется
select * from temp;
10 rows found
Если я выполню тот же сценарий в сеансе 2, пока сценарий в сеансе 1 все еще выполняется
declare
cursor abc is select * from temp for update nowait;
temp abc%rowtype;
begin
open abc;
-- do slow stuff here
close abc;
commit;
end;
Тогда я получаю ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired instead of waiting the lock to release.