20июн
Транзакция. Автономные транзакции
Автономные транзакции можно еще назвать вложенными транзакциями. Сам ORACLE использует такие транзакции при работе с последовательностями. Вы наверняка замечали, что если в транзакции используется последовательность, то её счетчик изменяется, даже если вы не завершили транзакцию. Очень красиво и наглядно автономная транзакция рассматривается у Тома Кайта. Поэтому приведу ниже выдержку из его работы с небольшими своими комментариями и примерами:
Автономные транзакции позволяют вам создать “транзакцию внутри транзакции”, которая зафиксирует или выполнит откат изменений, независимо от родительской транзакции. Они позволяют вам приостановить текущую выполняемую транзакцию, запустить новую, проделать некоторую работу и зафиксировать или откатить ее — все это не затрагивая состояния текущей выполняемой транзакции. Автономные транзакции предоставляют новый метод управления транзакциями вPL/SQL и могут быть использованы в следующих конструкциях.
- Анонимные блоки верхнего уровня.
- Локальные (процедура в процедуре), автономные или пакетные функции и процедуры.
- Методы объектных типов.
- Триггеры баз данных.
Пример
SQL> drop table dbst_t;
Table dropped.
SQL> create table dbst_t ( msg varchar2(25) );
Table created.
SQL> create or replace procedure dbst_NonAutonomous_Insert
2 as
3 begin
4 insert into dbst_t values ( 'NonAutonomous Insert' );
5 commit;
6 end;
7 /
Procedure created.
Создали обычную процедуру: вставляется запись и выполняется фиксация транзакции.
SQL> create or replace procedure dbst_Autonomous_Insert
2 as
3 pragma autonomous_transaction;
4 begin
5 insert into dbst_t values ( 'Autonomous Insert' );
6 commit;
7 end;
8 /
Procedure created.
Аналогичная процедура: вставка записи и фиксация транзакции. Но инструкция компилятору pragma autonomous_transaction требует, чтобы процедура выполнялась как автономная транзакция.
А теперь посмотрим результаты вызова этих процедур.
SQL> begin
2 insert into dbst_t values ( 'Anonymous Block' );
3 dbst_NonAutonomous_Insert;
4 rollback;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
SQL> select * from dbst_t;
MSG
-------------------------
Anonymous Block
NonAutonomous Insert
Почему такой результат? Commit, который находится в процедуре, зафиксировал результаты изменений, которые были проведены операторами insert в процедуре и в самом анонимном блоке. Поэтому роллбаку нечего было откатывать.
SQL> delete from dbst_t;
2 rows deleted.
SQL> commit;
Commit complete.
SQL>
SQL> begin
2 insert into dbst_t values ( 'Anonymous Block' );
3 dbst_Autonomous_Insert;
4 rollback;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
SQL> select * from dbst_t;
MSG
-------------------------
Autonomous Insert
А в этом анонимном блоке commit работает только для оператора insert в процедуре, так как это автономная транзакция. Внешнего оператора insert нашего анонимного блока эта фиксация не затрагивает. Оператор rollback откатывает изменения, которые сделал оператор insert into dbst_t values ( 'Anonymous Block' ).