Это не приведет к тупику. Это может произойти только тогда, когда два сеанса обновляют одну и ту же строку, поскольку они используют оптимистическую стратегию блокировки. Вот что происходит
Некоторые данные испытаний:
SQL> select * from t23
2 /
PERSON_NAME
-----------------------------------------------------------------------------
Fox in socks
Mr Knox
Sam-I-Am
The Lorax
John Doe
SQL>
Это ваш аноним (с исправленным sybtax):.
SQL> declare
2 cursor c_jd is
3 select *
4 from t23
5 where person_name = 'John Doe'
6 for update of person_name;
7 procedure foo_proc
8 ( p_name in t23.person_name%type)
9 is
10 cursor c_fp is
11 select *
12 from t23
13 where person_name = p_name
14 for update of person_name;
15 r_fp c_fp%rowtype;
16 begin
17 open c_fp;
18 fetch c_fp into r_fp;
19 update t23
20 set person_name = upper(r_fp.person_name)
21 where current of c_fp;
22 close c_fp;
23 end foo_proc;
24 begin
25 for onerow in c_jd loop
26 foo_proc(onerow.person_name);
27 end loop;
28 end;
29 /
PL/SQL procedure successfully completed.
SQL>
И это результат
SQL> select * from t23
2 /
PERSON_NAME
-----------------------------------------------------------------------------
Fox in socks
Mr Knox
Sam-I-Am
The Lorax
JOHN DOE
SQL>
Так ли это успешно? Потому что FOR UPDATE - это блокировка уровня сеанса. Эти две блокировки создаются в одном сеансе, поэтому Oracle достаточно умен, чтобы разрешить их без конфликтов. Как бы то ни было, если бы вы сделали что-то вроде объявления PRAGMA AUTONOMOUS_TRANSACTION в FOO_PROC (), это привело бы к
ORA-00060: deadlock detected while waiting for resource
Тот факт, что два вызова FOR UPDATE в одном сеансе не перестают работать таким образом, является важной частью архитектурного проектирования. Невозможно определить, выдает ли процедура блокировку, не глядя на исходный код. Поэтому, когда PROC_A () вызывает PROC_B (), он не имеет представления, вызывает ли эта процедура блокировку. Но PROC_A () может выдавать свою собственную блокировку, будучи уверенным, что это действие не приведет к сбою PROC_B (). Это хорошая вещь, потому что она поддерживает Закон Деметры и уменьшает связь.
Конечно, ваш сценарий является искусственным и будет отвергнут как плохая практика в обзоре кода, но это другая проблема!
редактировать
"Чтобы проверить это, я сделал FOO_PROC
автономный и не столкнулся с
тупиковой; это потому что это в
тот же сеанс? "
Вы уверены? Прагма AUTONOMOUS_TRANSACTION означает, что FOO_PROC () работает в своем собственном дискретном сеансе и не может получить блокировку:
SQL> declare
2 cursor c_jd is
3 select *
4 from t23
5 for update of person_name;
6 procedure foo_proc
7 ( p_name in t23.person_name%type)
8 is
9 pragma autonomous_transaction;
10 cursor c_fp is
11 select *
12 from t23
13 where person_name = p_name
14 for update of person_name;
15 r_fp c_fp%rowtype;
16 begin
17 dbms_output.put_line('Inside FP');
18 open c_fp;
19 fetch c_fp into r_fp;
20 update t23
21 set person_name = upper(r_fp.person_name)
22 where current of c_fp;
23 close c_fp;
24 commit;
25 end foo_proc;
26 begin
27 for onerow in c_jd loop
28 dbms_output.put_line('Outer loop START');
29 foo_proc(onerow.person_name);
30 dbms_output.put_line('Outer loop END');
31 end loop;
32 end;
33 /
Outer loop START
Inside FP
declare
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at line 11
ORA-06512: at line 18
ORA-06512: at line 29
SQL>
(я добавил несколько операторов DBMS_OUTPUT, чтобы показать, что происходит).
"Когда вы сказали пример кода, я
при условии плохой практики, что ты
значит? "
Я имел в виду цикл, приводящий в действие оператор SELECT, вызывающий другую программу, которая выбирает из той же таблицы. Действительно, который выбирает тот же ряд. Вообще говоря, мы должны избегать ненужной работы. У вас уже есть строка: зачем ее читать?