Владимир Пржиялковский
Из новых видов триггеров, пополнивших арсенал разработчика в версии 8i, шесть уже нашли свое отражение в одном из более ранних выпусков "Мастерской Oracle". Это так называемые "триггеры для событий уровня схемы БД" (schema-level event triggers). Здесь можно поговорить еще о пяти: о "триггерах для событий уровня системы" (database-level event triggers). Они запускаются при возникновении в системе (СУБД) следующих событий:
Событие |
Описание триггера |
SERVERERROR |
Триггер срабатывает при возникновении серверной ошибки |
LOGON |
Триггер срабатывает при успешном подключении к системе клиентского приложения |
LOGOFF |
Триггер срабатывает перед отключением клиентского приложения от СУБД |
STARTUP |
Триггер срабатывает немедленно после открытия БД |
SHUTDOWN |
Триггер срабатывает непосредственно перед попыткой закрыть СУБД "нормальным образом", то есть всеми вариантами команды SHUTDOWN кроме варианта SHUTDOWN ABORT |
Общий синтаксис описания триггеров схемы таков:
CREATE [ OR REPLACE ] TRIGGER имя_триггера
{ BEFORE / AFTER }
{ SERVERERROR / LOGON / LOGOFF / STARTUP / SHUTDOWN }
ON DATABASE
BEGIN
текст на PL/SQL
END;
С каждым событием из таблицы выше связано несколько атрибутов. Фактически эти атрибуты - системные функции, возвращающие при обращении к ним из тела триггера некоторый результат. Ниже эти атрибуты перечисляются, причем первые шесть из них нам уже знакомы по триггерам событий уровня схемы.
Имя |
Тип |
Описание |
SYSEVENT |
VARCHAR2(30) |
Имя системного события, активизировавшего триггер |
LOGIN_USER |
VARCHAR2(30) |
Имя пользователя, вышедшего на сеанс работы с Oracle |
INSTANCE_NUM |
NUMBER |
Имя экземпляра СУБД |
DATABASE_NAME |
VARCHAR2(50) |
Имя БД |
SERVER_ERROR |
NUMBER |
Функция, возвращающая номер ошибки на указанном месте магазина ошибок. 1 соответствует верхушке магазина. Пример: SERVER_ERROR(2) выдаст номер ошибки на втором от верха месте в магазине. |
IS_SERVERERROR |
BOOLEAN |
Функция, возвращающая TRUE при наличии указанной ошибке в текущем магазине ошибок; FALSE в противном случае. |
Вот какие правила и атрибуты свойственны каждому событию:
Событие |
Правило |
Атрибуты |
SERVERERROR |
По умолчанию триггер будет срабатывать при всех событиях. Однако специальным указанием можно "сказать", чтобы триггер срабатывал только при интересующих нас событиях. |
SYSEVENT
LOGIN_USER
INSTANCE_NUM
DATABASE_NAME
SERVER_ERROR
IS_SERVERERROR |
LOGON |
Условие можно указать, воспользовавшись USERID( ) или USERNAME( ) |
SYSEVENT
LOGIN_USER
INSTANCE_NUM
DATABASE_NAME |
LOGOFF |
Условие можно указать, воспользовавшись USERID( ) или USERNAME( ) |
SYSEVENT
LOGIN_USER
INSTANCE_NUM
DATABASE_NAME |
STARTUP |
В теле триггера не допускается использование операций с БД - DML и запросов. Можно, однако, запускать программы (например, listener), закреплять в SGA пакеты и т. д. |
SYSEVENT
LOGIN_USER
INSTANCE_NUM
DATABASE_NAME |
SHUTDOWN |
В теле триггера не допускается использование операций с БД - DML и запросов. Можно, однако, останавливать программы (например, listener), или запускать (например, сбора статистики работы СУБД и занесения ее в журнал) |
SYSEVENT
LOGIN_USER
INSTANCE_NUM
DATABASE_NAME |
При написании триггера нужно учитывать следующие обстоятельства:
- При запуске триггера событий в СУБД Oracle открывает автономную транзакцию, осуществляет сам запуск и фиксирует (commit) выполнение всех DML-операций безотносительно к логике транзакций пользователя.
- В определении триггеров LOGON, STARTUP и SERVERERROR можно указывать только слово AFTER. Если указать BEFORE, при трансляции будет выдана ошибка.
- Аналогично, в определении триггеров LOGOFF и SHUTDOWN можно указывать только BEFORE.
- Обращения из процедур DBMS_OUTPUT не дадут на экране никакой выдачи в пределах текущего сеанса. Для того, чтобы как-то записать информацию, нужно будет воспользоваться записью в таблицы, в файл ОС или средством pipeline.
- Триггер на SERVERERROR не срабатывает на следующие пять событий: ORA-01403, ORA-01422, ORA 04030, ORA-01034 и ORA-01007.
Триггеры событий в СУБД могут использоваться в разных целях: для прикрепления объектов к SGA при старте системы, для отслеживания входов в БД, для трассировки ошибок.
Так, прикрепление наиболее часто используемых пакетов в SGA при старте системы может (в случае интенсивной загрузки СУБД) ускорить среднее время обращения к процедурам этих пакетов (они не будут участвовать в страничном обмене) и уменьшить отрицательные последствия, вызванные фрагментацией динамически выделяемого пространства SGA в процессе работы. Следующий пример Стивена Фойерстина показывает, как можно таким образом закрепить в SGA пакеты STANDARD и DBMS_STANDARD, встроенные в систему:
CREATE OR REPLACE TRIGGER pin_code_on_startup
AFTER STARTUP ON DATABASE
BEGIN
DBMS_SHARED_POOL.KEEP (‘SYS.STANDARD’, ‘P’);
DBMS_SHARED_POOL.KEEP (‘SYS.DBMS_STANDARD’, ‘P’);
END;
/
Для закрепления пользовательских пакетов, включающих требуемые процедуры или функции, можно самостоятельно составить более сложные схемы, базирующиеся в конце-концов на триггере AFTER STARTUP.