Недавно пришлось провести некоторые тесты. Когда возникает необработанное исключение, кажется, что Oracle выполняет частичный откат до точки самого верхнего содержащего блока начала или фиксации для одного и того же сеанса (не всегда полностью назад к предыдущей фиксации). Дана таблица с int id и varchar2 val и proc:
CREATE OR REPLACE PROCEDURE PROC_AUTO_COMMIT_TEST(
p_id int, p_val varchar2, p_cmd varchar2
) IS
BEGIN
if (p_cmd = 'init') then
delete from TEMP_AUTOCOMMIT_TEST;
insert into TEMP_AUTOCOMMIT_TEST values(1,'one');
insert into TEMP_AUTOCOMMIT_TEST values(2,'two');
insert into TEMP_AUTOCOMMIT_TEST values(3,'three');
commit;
else
update TEMP_AUTOCOMMIT_TEST
set val = p_val
where id = p_id;
if (p_cmd = 'throw') then
insert into TEMP_AUTOCOMMIT_TEST values(3,'THREE'); -- throws
end if;
end if;
END PROC_AUTO_COMMIT_TEST;
Затем выполните это:
begin
PROC_AUTO_COMMIT_TEST(0, null, 'init');
begin
PROC_AUTO_COMMIT_TEST(1, 'ONE', null);
end;
begin
PROC_AUTO_COMMIT_TEST(2, 'TWO', null);
PROC_AUTO_COMMIT_TEST(3, 'THREE', 'throw');
end;
end;
Откат полностью до коммита внутри 'init' (ОДИН откат тоже).
По сравнению с их превышением по порядку (из либо Жабы (автоматическая фиксация выключена, F9 в каждом блоке, f5 для всего) или Sqlplus с / 'между
begin
PROC_AUTO_COMMIT_TEST(0, null, 'init');
end;
begin
PROC_AUTO_COMMIT_TEST(1, 'ONE', null);
end;
begin
PROC_AUTO_COMMIT_TEST(2, 'TWO', null);
PROC_AUTO_COMMIT_TEST(3, 'THREE', 'throw');
end;
Исключение, возникающее в ТРИ, затем возвращается к «ОДИН». Однако «ONE» все еще необходимо откатить или зафиксировать, поскольку он удерживает блокировку строки (проверено с помощью браузера сеансов в TOAD). Называя это частичным откатом, потому что он не полностью возвращается к фиксации в вызове 'init' и оставляет строку заблокированной. Я предполагаю, что этот случай ближе к тому, что может делать PHP и другие коннекторы.