Дискретные и автономные транзакции в Oracle

Дискретные и автономные транзакции в базе OracleЧтобы помочь в управлении транзакциями, СУБД Oracle позволяет использовать два специальных типа транзакций — дискретные транзакции и автономные транзакции. В этой статье блога мы опишем обе концепции.

 

Дискретные транзакции

Чтобы повысить скорость выполнения транзакций, база данных Oracle Database позволяет явно использовать дискретные транзакции. Когда транзакция специфицируется как дискретная, Oracle пропускает определенные рутинные операции, влекущие за собой накладные расходы, такие как сохранение записей отмены, тем самым ускоряя транзакцию в целом. Oracle не модифицирует блоки данных до тех пор, пока транзакция не будет зафиксирована.

Процедура BEGIN_DESCRETE_TRANSACTION, входящая в пакет DBMS_TRANSACTION, служит для реализации стратегии дискретных транзакций. Краткие транзакции выполняются быстрее при использовании этой процедуры, но если дискретная транзакция случается во время выполнения длительных запросов, и эти запросы требуют данных, модифицируемых этими транзакциями, могут возникнуть проблемы. Поскольку дискретные транзакции пропускают процесс записи данных отмены, длительно выполняющиеся запросы не могут получить согласованное представление данных. Oracle не генерирует записей отмены для дискретных транзакций, поскольку блоки данных не модифицируются до тех пор, пока дискретная транзакция не зафиксирована.

 

Автономные транзакции

Транзакция может быть составной частью другой транзакции. В таких случаях родительская транзакция называется главной, а независимая дочерняя транзакция — автономной. Автономная транзакция формально определена как независимая, которая может быть вызвана из другой транзакции. Обратите внимание, что хотя дочерняя транзакция вызывается из родительской, она не зависит от родительской транзакции.

Пакеты, процедуры, функции и триггеры могут включать в себя транзакции, помеченные как автономные. В главную транзакцию потребуется включить некоторую директиву, чтобы Oracle знал, что вы намерены использовать автономную транзакцию внутри главной. Как и любая обычная транзакция, автономная транзакция может иметь свои собственные операторы ROLLBACK и COMMIT. Главная транзакция, используя автономную, может приостанавливать и выполнять автономную транзакцию, а затем продолжать с места остановки. Другими словами, вы сохраняете контекст вызывающей транзакции, выполняете операторы SQL как часть автономной транзакции, фиксируете или откатываете транзакцию, а затем продолжаете выполнение родительской транзакции до возврата в контекст вызывающей транзакции. Обратите внимание, что автономная транзакция не разделяет ресурсы, подобные блокировкам, с родительской транзакцией.

Автономные транзакции обеспечивают разработчикам возможность создания более тонко гранулированных транзакций, когда транзакция перестает быть субъектом правила “все или ничего”. Вложенные автономные транзакции можно фиксировать и откатывать независимо от вызова родительской транзакции.


На заметку! Если вы не используете автономных транзакций, то все изменения в сеансе будут зафиксированы или отменены сразу (по команде COMMIT или ROLLBACK). Автономные транзакции дают возможность фиксировать или отменять изменения в подпрограммах, независимо от главной программы. Также следует отметить, что если не зафиксировать или не откатить автономную транзакцию, то Oracle выдаст сообщение об ошибке.


В листинге ниже представлен простой пример автономной транзакции. Обратите внимание, что оператор (директива компилятора) PRAGMA_AUTONOMOUS_TRANSACTION заставляет Oracle пометить присоединенную часть кода — функцию loans — как автономную.


 

SQL> CREATE OR REPLACE package lending AS function loans
        (user_id integer) return real;
     -- добавить дополнительные функции и/или пакеты
     END lending;

     CREATE OR REPLACE PACKAGE BODY lending AS
          function loans (user_id integer) return REAL IS
               PRAGMA AUTONOMOUS_TRANSACTION;
               loan_bal REAL;
          BEGIN
               -- здесь находится код
          END;

          -- сюда помещаются любые дополнительные функции и/или пакеты
     END lending;
SQL>

Автономные транзакции обеспечивают высокую гибкость. Вы можете приостановить главную транзакцию, запустить автономную транзакцию, а затем возобновить обработку главной транзакции. Зафиксированные изменения автономной транзакции видимы главной транзакции, потому что уровень изоляции по умолчанию в Oracle — READ COMMITTED, что означает возможность транзакции видеть все зафиксированные данные.

У автономных транзакций много применений. Например, их можно использовать для отправки журнальных сообщений об ошибках. Можно иметь единственную процедуру, которая пишет сообщения об ошибках в журнальную таблицу, и вызывать эту процедуру в качестве автономной транзакции из обычной транзакции. В листинге ниже демонстрируется запись в таблицу сообщения об ошибке.


 

SQL> CREATE OR REPLACE PROCEDURE error_log(error_msg in varchar2,
        procedure_name IN VARCHAR2 IS
        PRAGMA AUTONOMOUS_TRANSACTION;

     BEGIN
        INSERT INTO log_table (error_msg, procedure_name)
        VALUES (error_msg,procedure_name));
        COMMIT;
     EXCEPTION
        WHEN OTHERS THEN ROLLBACK;
     END;
SQL>

Автономные транзакции могут служить и другим целям в базе данных Oracle. Например, они могут позволить обработку нестандартных проблем кода PL/SQL, таких как использование операторов DDL в триггерах. Автономные транзакции также удобны для проведения аудита запросов базы данных и неудавшихся (неавторизованных) действий в базе данных.

В листинге ниже показывает пример применения средства автономной транзакции для аудита (предположительно) неавторизованной активности по обновлению. Даже если пользователю не удастся попытка обновления, его имя будет запротоколировано в таблице аудита, если вы закодируете простую пару триггеров, использующих средство автономных транзакций.


SQL> CREATE OR REPLACE TRIGGER aud_bef_trig
        BEFORE INSERT ON emp FOR EACH ROW
        DECLARE
          PRAGMA AUTONOMOUS_TRANSACTION
        BEGIN
           INSERT INTO audit_employee VALUES (
             :new.username, 'перед вставкой', sysdate);
           COMMIT;
        END;

SQL> CREATE OR REPLACE TRIGGER aud_aft_trig
      AFTER INSERT ON emp FOR EACH ROW
      DECLARE
         PRAGMA AUTONOMOUS TRANSACTION
      BEGIN
        INSERT INTO audit_emp VALUES (
           :new.username, 'после вставки', sysdate);
        COMMIT;
      END;
SQL>

Обратите внимание на то, что просто использовать пару обычных триггеров для аудита активности в базе данных Oracle можно не всегда, так как данные аудита, представленные триггерами, не будут записаны, если оператор, вызвавший триггер, будет отменен.

Вас заинтересует / Intresting for you:

Oracle изменения изменений!
Oracle изменения изменений! 2261 просмотров Stas Belkov Tue, 21 Nov 2017, 13:18:46
Oracle Personal Edition
Oracle Personal Edition 5188 просмотров Надин Tue, 21 Nov 2017, 13:32:12
Разница между базой данных и э...
Разница между базой данных и э... 2136 просмотров Александров Попков Tue, 21 Nov 2017, 13:18:46
Фиксация и откат транзакций в ...
Фиксация и откат транзакций в ... 3572 просмотров Antoniy Tue, 21 Nov 2017, 13:18:46
Войдите чтобы комментировать

Oracle_Admin аватар
Oracle_Admin ответил в теме #9854 02 фев 2021 18:12
Да! Хороший пример. Многое объясняет...
Borberd аватар
Borberd ответил в теме #9235 25 сен 2018 04:24
Спасибо за пример автономной транзакции Oracle для аудита!