![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Аудит триггером составной транзакции
Гость © (2010-02-03 10:40:00)Доброго дня!
Есть программа, которая выполняет в одной транзакции delete, insert, update. Есть триггер:
create or replace trigger SAMPLE_AUD
before insert or delete or update on SAMPLE_TABLE
for each row
, задача которого отловить все изменения и записать в таблицу аудита. Проблема в том, что отлавливается только insert. Можно ли сделать так, чтобы триггер отрабатывал на каждую команду в транзакции?
Sergey13 (2010-02-05 10:30:00) [41]> [23] ANB (05.02.10 10:05)
Он просто тупо большой и достаточно сложный если в него смотреть.
Дистрибутив ФБ весит 2.5 метра и сервер и клиент. Сколько весит Оракл?
ANB (2010-02-05 10:05:00) [42]
> Для "некритичной базки" ни к чему юзать Оракл
А что юзать то ?
Оракл :
1) халявый
2) ставится за 5 минут задавая 3 вопроса
3) удобный
Sergey13 (2010-02-05 09:51:00) [43]> [18] Кщд (04.02.10 17:29)
> некритичной базке с 3-5 таблиц никто не будет поднимать
> архивлоги - это просто ни к чему
Для "некритичной базки" ни к чему юзать Оракл (хотя конечно не возбраняется 8-), и уж тем более прикручивать аудит. ИМХО.
Кщд (2010-02-05 05:55:00) [44]>Игорь Шевченко © (05.02.10 00:55) [20]
особенно хорош и гибок - FGA
никто не спорит, да и пользовать его в той же 10-ке - очень удобно
вот только в обычной такой системе, где авторизация/аутентификация самописные(т.е. коннект происходит под одним пользователем Oracle), система разграничение прав своя и все изменения(DML) должны быть увязаны с OPERATION_LOG.ID(т.е. выполненной пользователем операции (или, например, идентификатором web-сессии), - все эти внутренние и, безусловно, эффективные инструменты несколько не к месту
другими словами, это, скорее, инструментарий dba, а не разработчика
Игорь Шевченко (2010-02-05 00:55:00) [45]RTFM Кулибиным:
http://download.oracle.com/docs/cd/B10500_01/server.920/a96521/audit.htm
http://www.oracle-base.com/articles/8i/Auditing.php
http://www.citforum.ru/database/oracle/audit/
Кщд (2010-02-04 20:49:00) [46]>Sergey13 © (04.02.10 13:14) [15]
перечитал Ваш пост внимательно)
>Разумеется в некоторых системах аудит необходим даже по закону, но >обычно люди пишущие его не задают вопросов на форумах.
ещё как задают))
здесь ещё немного кода и специфичных названий полей/таблиц - есть примеры, когда выкладывают код в несколько десятков килобайт...
только когда(и если) работодатель видит потроха базы и кода в форуме - ни к чему хорошему для вопрошавшего это не приводит
Кщд (2010-02-04 17:29:00) [47]>Sergey13 © (04.02.10 13:20) [16]
logminer пишет IP пользователя?)
а если серьезно, то, например, на простенькой, некритичной базке с 3-5 таблиц никто не будет поднимать архивлоги - это просто ни к чему
да и с помощью sql работать куда как приятнее - опять же можно в софтину клиентскую привязать показ изменений
Кщд (2010-02-04 17:25:00) [48]>ANB (04.02.10 12:30) [14]
>Да ничего страшного вообще то
0!=null - логическая ошибка
т.о. при изменении 0 на null и обратно, изменение не будет учтено
>Вполне нормально. Старое и новое значение.
вопрос был "зачем"
если бездумно плодить данные - нормально, то остается только умыть руки
>SELECT SEQ_INASTRBUD_AUD.NEXTVAL INTO New_Idaud FROM Dual;
т.е. если ID2 > ID1, то изменения в ID2 - более поздние, так?
>Короче, вполне себе так нормальный триггер. Я бы еще поле для sysdate добавил - не помешает.
timestamp
и, желательно, с local time zone
впрочем, это уже излишество, но весьма полезное время от времени
Sergey13 (2010-02-04 13:20:00) [49]Плюсом про аудит.
В Оракле (насколько я понял это он) вроде как есть штатное средство по работе со штатными логами. Log Miner вроде называется. Я с ним не разбирался, но вроде как по отзывам вполне работоспособен. А логах оракла есть все.
Sergey13 (2010-02-04 13:14:00) [50]Насчет аудита я скажу так. Я бы трижды подумал на тему - а нужен ли он такой. Пробовал несколько раз делать такое - очень скоро аудитные таблицы начинают превосходить исходные по объему на порядки. При этом используется он ОЧЕНЬ (обычно) редко и не дает особо ничего. Ну нашли виновника, и что? "Ну ошибся я, с кем не бывает". И ВСЕ. Я бы просто добавил логин юзера и дату последней модификации записи в основную таблицу. В 99% случаев этогшо достаточно.
Разумеется в некоторых системах аудит необходим даже по закону, но обычно люди пишущие его не задают вопросов на форумах.
ИМХО
ЗЫ: Я так и не понял как влияло некорректное сравнение с нулом на секцию тригера про удаление.
ANB (2010-02-04 12:30:00) [51]
> null = 0
> с такой логикой далеко не уедешь
Да ничего страшного вообще то
> также, не ясно, зачем при update плодить две записи
Вполне нормально. Старое и новое значение.
> но как Вы собираетесь определять очередность изменений при
> таком подходе
SELECT SEQ_INASTRBUD_AUD.NEXTVAL INTO New_Idaud FROM Dual;
Короче, вполне себе так нормальный триггер. Я бы еще поле для sysdate добавил - не помешает.
И стандартная ошибка при сравнении (забыли про null). Я так тоже люблю косячить. Правда, в последнее время уже очень редко.
Кщд (2010-02-03 18:33:00) [52]Гость (03.02.10 15:24) [9]
null = 0
с такой логикой далеко не уедешь
также, не ясно, зачем при update плодить две записи и почему в логе нет timestamp?
допустим, двойной вставкой при update страхуетесь от того, что два пользователя одновременно редактируют запись(а Вам, видимо, хочется видеть что менял пользователь и на что, на случай lost update), но как Вы собираетесь определять очередность изменений при таком подходе - совершенно непонятно
trim, опять же, где нужно и где не нужно
и принято сообщать, СУБД и версию
удачи)
Anatoly Podgoretsky (2010-02-03 16:01:00) [53]> Ega23 (03.02.2010 15:55:11) [11]
Update по сути такой и есть, а внутреннея реализация не интересна.
Ega23 (2010-02-03 15:55:00) [54]А как в Oracle Update работает?
У меня складывается глубокое убеждение, что в MSSQL он "в кишках" как delete-insert работает.
Sergey13 (2010-02-03 15:42:00) [55]> [9] Гость (03.02.10 15:24)
А как это влияло на НЕсрабатывании на удаление? Или ты не удалял?
Гость (2010-02-03 15:24:00) [56]Спасибо, все решилось!
Дело было в ошибке сравнения с NULL. Надо так:
IF Updating THEN
IF nvl(:old.IDNTYPBUDG, 0) <> nvl(:new.IDNTYPBUDG, 0) OR
nvl(:old.IDNBACC, 0) <> nvl(:new.IDNBACC, 0) OR
nvl(:old.IDNBUDGET, 0) <> nvl(:new.IDNBUDGET, 0) OR
nvl(:old.IDINASTRBUD, 0) <> nvl(:new.IDINASTRBUD, 0) THEN
Кщд (2010-02-03 13:33:00) [57]триггеры аудита обычно вешают на after
а конкретно по теме: тест-кейс из sqlplus в студию, пожалуйста
Гость (2010-02-03 11:12:00) [58]пробовал, отрабатывает один, по последней команде
Sergey13 (2010-02-03 11:10:00) [59]> [5] Гость (03.02.10 10:56)
на первый взгляд вроде все логично.
А если сделать три отдельных тригера на каждое действие?
Гость (2010-02-03 10:56:00) [60]
create or replace trigger INASTRBUD_AUD
before insert or delete or update on INASTRBUD
for each row
declare
New_Idaud xx_audit.INASTRBUD_AUD.IDAUD%TYPE;
begin
SELECT SEQ_INASTRBUD_AUD.NEXTVAL INTO New_Idaud FROM Dual;
IF Updating THEN
IF :old.IDNTYPBUDG <> :new.IDNTYPBUDG OR :old.IDNBACC <> :new.IDNBACC OR
:old.IDNBUDGET <> :new.IDNBUDGET OR
:old.IDINASTRBUD <> :new.IDINASTRBUD THEN
INSERT INTO xx_audit.INASTRBUD_AUD
(IDNTYPBUDG,
IDNBACC,
IDNBUDGET,
IDINASTRBUD,
IDAUD,
DML_TYPE,
DML_TYPEU,
TERMINAL,
OS_USER,
IP_ADRES,
SESSION_USER)
VALUES
(:old.IDNTYPBUDG,
:old.IDNBACC,
:old.IDNBUDGET,
:old.IDINASTRBUD,
New_Idaud,
'U',
'0',
TRIM(Sys_Context('userenv', 'TERMINAL')),
TRIM(Sys_Context('userenv', 'OS_USER')),
TRIM(Sys_Context('userenv', 'IP_ADDRESS')),
TRIM(Sys_Context('userenv', 'SESSION_USER')));
INSERT INTO xx_audit.INASTRBUD_AUD
(IDNTYPBUDG,
IDNBACC,
IDNBUDGET,
IDINASTRBUD,
IDAUD,
DML_TYPE,
DML_TYPEU,
TERMINAL,
OS_USER,
IP_ADRES,
SESSION_USER)
VALUES
(:new.IDNTYPBUDG,
:new.IDNBACC,
:new.IDNBUDGET,
:new.IDINASTRBUD,
New_Idaud,
'U',
'1',
TRIM(Sys_Context('userenv', 'TERMINAL')),
TRIM(Sys_Context('userenv', 'OS_USER')),
TRIM(Sys_Context('userenv', 'IP_ADDRESS')),
TRIM(Sys_Context('userenv', 'SESSION_USER')));
END IF;
ELSIF Inserting THEN
INSERT INTO xx_audit.INASTRBUD_AUD
(IDNTYPBUDG,
IDNBACC,
IDNBUDGET,
IDINASTRBUD,
IDAUD,
DML_TYPE,
DML_TYPEU,
TERMINAL,
OS_USER,
IP_ADRES,
SESSION_USER)
VALUES
(:new.IDNTYPBUDG,
:new.IDNBACC,
:new.IDNBUDGET,
:new.IDINASTRBUD,
New_Idaud,
'I',
'',
TRIM(Sys_Context('userenv', 'TERMINAL')),
TRIM(Sys_Context('userenv', 'OS_USER')),
TRIM(Sys_Context('userenv', 'IP_ADDRESS')),
TRIM(Sys_Context('userenv', 'SESSION_USER')));
ELSE
INSERT INTO xx_audit.INASTRBUD_AUD
(IDNTYPBUDG,
IDNBACC,
IDNBUDGET,
IDINASTRBUD,
IDAUD,
DML_TYPE,
DML_TYPEU,
TERMINAL,
OS_USER,
IP_ADRES,
SESSION_USER)
VALUES
(:old.IDNTYPBUDG,
:old.IDNBACC,
:old.IDNBUDGET,
:old.IDINASTRBUD,
New_Idaud,
'D',
'',
TRIM(Sys_Context('userenv', 'TERMINAL')),
TRIM(Sys_Context('userenv', 'OS_USER')),
TRIM(Sys_Context('userenv', 'IP_ADDRESS')),
TRIM(Sys_Context('userenv', 'SESSION_USER')));
END IF;
end INASTRBUD_AUD;