|
Программирование >> Oracle
Глава 15 ности транзакция при этом не фиксируется. Кроме того, при откате транзакции увеличенное значение последовательности остается - оно не откатывается вместе с транзакцией, поскольку уже зафиксировано. Управление пространством, проверка и другие внутренние действия сервера также выполняются рекурсивно. Просто эта возможность не предлагалась для широкого использования. Теперь, увидев действие автономной транзакции, давайте разберемся, для чего такие транзакции можно использовать. Когда использовать автономные транзакции? В этом разделе мы рассмотрим ряд ситуаций, когда могут пригодиться автономные транзакции. Проверка, записи которой не могут быть отменены В прошлом разработчики приложений часто задавали вопрос: Как зарегистрировать в журнале проверки попгтку изменить защищенную информацию? . Они хотели не только предотвратить попытку изменения, но и сохранить информацию о такой попытке. В прошлом многие (безуспешно) пытались применять для этого триггеры. Триггер срабатывает при выполнении изменения; определяет, что пользователь изменяет данные, которые изменять не должен; создает запись в журнале проверки и завершает изменение как неудавшееся (вызывая откат). К сожалению, если изменение не выполняется, откатывается и запись в журнале проверки - неделимость операторов означает все или ничего . Теперь, с помощью автономных транзакций, можно безопасно сохранить запись о попытке выполнения несанкционированного изменения и откатить само изменение, что позволяет уведомить пользователя: Вы не имеете права изменять эти данные, и мы зафиксировали вашу попытку их изменить . Интересно отметить, что встроенное средство AUDIT сервера Oracle уже давно позволяло регистрировать с помощью автономных транзакций безуспешные попытки изменить информацию. Наличие такой возможности у разработчика позволяет ему создавать собственные, более гибкие системы проверки. Вот небольшой пример. Скопируем таблицу ЕМР из схемы пользователя SCOTT и создадим таблицу для журнала аудита (audit trail table), куда будем записывать кто попытался изменить таблицу ЕМР и когда была сделана эта попытка, а также что именно пытались изменить. Для автоматического сохранения этой информации для таблицы ЕМР будет создан триггер, оформленный как автономная транзакция: tkyte@TKYTE816>create table emp 2 as 3 select * from scott.emp; Table created. tkyte@TKYTE816> grant all on emp to scott; Автономные транзакции 1165 Grant succeeded. tkyte@TKYTE816> create table audit tab (username timestamp varchar2(30) default user, date default sysdate, varchar2(4000) Table created. Затем необходимо создать триггер проверки изменений таблицы ЕМР. Обратите внимание на использование автономной транзакции. Этот триггер предотвращает изменение записи о сотруднике любым пользователем, если этот сотрудник не является его подчиненным. Запрос с конструкцией CONNECT BY реализует поиск по всей иерархии подчиненных текущего пользователя. Запрос будет проверять, принадлежит ли запись, которую пользователь пытается изменить, одному из его подчиненных: tkyte@TKYTE816> create or replace trigger EMP AUDIT 7 8 9 10 11 12 13 14 15 16 17 18 21 22 24 25 26 before update on emp for each row declare pragma autonomous transaction; l cnt number; begin select count(*) from dual where EXISTS into l cnt (select null from emp where empno = start with mgr connect by prior :new.empno = (select empno from emp where ename empno - mgr); USER) if ( l cnt then insert values commit; = 0 ) into audit tab (msg) (Attempt to update :new.empno); raise application error(-20001, end if; Access Denied); end; Trigger created. Итак, мы создали таблицу ЕМР, имеющую иерархическую структуру (задаваемую рекурсивным отношением EMPNO/MGR). Имеется также таблица AUDIT TAB, в которую будут записываться неудавшиеся попытки изменить информацию. Создан триггер, позволяющий изменять запись о сотруднике только его руководителю или руководителю руководителя (и так далее). 1166 Глава 15 В этом триггере надо обратить внимание на следующее. В определении триггера указана прагма AUTONOMOUS TRANSACTION. Весь триггер выполняется как автономная транзакция по отношению к текущей. Вкратце объясню понятие прагма (pragma). Прагма - это директива компилятору - способ потребовать от компилятора выполнения определенной опции компиляции. Есть и другие прагмы, описание которых можно найти в руководстве PL/SQL Users Guide and Reference. Триггер по таблице ЕМР читает данные из таблицы ЕМР в запросе. Подробнее о том, почему это существенно, - чуть ниже. Триггер фиксирует транзакцию. Раньше это бтло невозможно - триггеры никогда не фиксировали изменения. На самом деле триггер не фиксирует изменения, вызвавшие его срабатывание. Он фиксирует только изменения, сделанные им самим (добавленную запись проверки). Давайте теперь рассмотрим, как все это работает: tkyte@TKYTE816> update emp set sal = sal*10; update emp set sal = sal*10 ERROR at line 1: OBA-20001: Access Denied ORA-06512: at TKYTE.EMP AUDIT , line 22 ORA-04088 : error during execution of trigger TKYTE.EMP AUDIT tkyte@TKYTE816> column msg format a30 word wrapped tkyte@TKYTE816> select * from audit tab; USERNAME TIMESTAMP MSG TKYTE 15-APR-01 Attempt to update 7369 Итак, триггер среагировал на попытку изменения и предотвратил его, записав при этом информацию о попытке в таблицу проверки (обратите внимание, как с помощью значений по умолчанию, заданных после ключевого слова DEFAULT в операторе CREATE TABLE, в запись автоматически добавлены значения встроенных функций USER и SYSDATE). Зарегистрируемся от имени пользователя, который имеет право выполнять изменения, и попробуем выполнить ряд операторов: tkyte@TKYTE816> connect scott/tiger scott@TKYTE816> update tkyte.emp set sal = sal*1.05 where ename = ADAMS; 1 row updated. scott@TKYTE816> update tkyte.emp set sal = sal*1.05 where ename = SCOTT ; update tkyte.emp set sal = sal*1.05 where ename = SCOTT ERROR at line 1: ORA-20001: Access Denied ORA-06512: at TKYTE.EMP AUDIT , line 22 ORA-04088: error during execution of trigger TKYTE.EMP AUDIT
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |