Комрады, поделитесь, плз, практическими советами и хитростями по логированию работы БД. Интересуют детали, типа: структура таблицы логов, примеры триггеров и проч.проч.
проще всего подсмотреть у Хвастунова. у него такая система уже внедрена в IBExpert.
ОК, тогда такой вопрос: как из системных таблиц "достать" имя текущей в триггере?
Док ОК, тогда такой вопрос: как из системных таблиц "достать" имя текущей в триггере? руками.
sim_84 писал(а) Mon, 05 September 2022 18:24 Имя текущей чего? И текущей куда? Док, если просто посмотреть на структуры системных таблиц, масса вопросов отпадёт сама собой. В данном случае - вторая строчка в структуре таблицы rdb$triggers
Док писал(а) Mon, 05 September 2022 17:59 ОК, тогда такой вопрос: как из системных таблиц "достать" имя текущей в триггере? Из никакой. Ты пишешь триггер и не знаешь - для какой он таблицы ?
hvlad Ты пишешь триггер и не знаешь - для какой он таблицы ? я так полагаю, что это "универсальный триггер". (шаблон) зы: мопед не мой, если чо
МП писал(а) Mon, 05 September 2022 18:50 hvlad Ты пишешь триггер и не знаешь - для какой он таблицы ? я так полагаю, что это "универсальный триггер". (шаблон) зы: мопед не мой, если чо ты оракулом не пробовал подрабатывать? Который раз угадываешь мои хотелки
hvlad писал(а) Mon, 05 September 2022 18:45 Док писал(а) Mon, 05 September 2022 17:59 ОК, тогда такой вопрос: как из системных таблиц "достать" имя текущей в триггере? Из никакой. Ты пишешь триггер и не знаешь - для какой он таблицы ? тупо в каждой табл в триггере прописывать название евоной таблицы - не по-программистски. Но, если так разрешено, то сделаю так о_О. зы. думал, щас научат гуманитария старшие товарищи, как тру кодеры код пишут. Заодно узнаю кучу новых терминов. А фиг
Старый Плюшев писал(а) Mon, 05 September 2022 18:30 Док, если просто посмотреть на структуры системных таблиц, масса вопросов отпадёт сама собой. В данном случае - вторая строчка в структуре таблицы rdb$triggers Спасибо, Алексан Владимыч, от нынешней братии такой душевной подсказки не дождесси - все норовят разраженно подколоть. Хотел слентяйничать - теперь уж опять туда полезу, пока не выучу все поля наизусть
Этот вопрос появляется каждый раз, когда в очередной раз начинают изобретать этот велосипед. Ответ не меняется годами. ЗЫ масло - масляное
МП писал(а) Mon, 05 September 2022 18:50 hvlad Ты пишешь триггер и не знаешь - для какой он таблицы ? я так полагаю, что это "универсальный триггер". (шаблон) Это и не подлежало сомнению. Штука в том, что "универсальный" он только до момента применения (инстанциирования) шаблона. И почему-то авторам не приходит в голову что, хотя имя таблицы в заголовке триггера уже является пар-ром шаблона, они почему-то считают "некомильфо" использовать этот же пар-р в теле триггера. Я никогда не мог этого понять... ЗЫ я не ругаюсь, если что
Док, а, кстати, сакраментальный вопрос контрразведчика - с какой целью интересуетесь? В смысле что хочешь с лога поиметь?
У меня есть несколько систем логирования, наиболее общая и понятная - это логирование таблиц справочников, у которых первичный ключ - ID и он идентифицирует объект. Т.е. когда нам интересна история изменения объекта - то идентификатор этого объекта - ID. Сам лог сделан вот так. CREATE GENERATOR GEN_LOGS_ID; CREATE TABLE LOGS ( ID INTEGER NOT NULL, TNAME VARCHAR(31), FNAME VARCHAR(31), ID_SRC INTEGER, A CHAR(1), VAL VARCHAR(1000), VAL_OLD VARCHAR(1000), A_DT TIMESTAMP default current_timestamp, A_USER VARCHAR(32) default current_user, A_IP VARCHAR(253), A_EXE VARCHAR(253) ); ALTER TABLE LOGS ADD CONSTRAINT LOGS_PK PRIMARY KEY (ID); CREATE INDEX LOGS_A_DT ON LOGS (A_DT); CREATE INDEX LOGS_FNAME ON LOGS (FNAME); CREATE INDEX LOGS_ID_SRC ON LOGS (ID_SRC); CREATE INDEX LOGS_TNAME ON LOGS (TNAME); SET TERM ^ ; CREATE OR ALTER TRIGGER LOGS_BI_ID FOR LOGS ACTIVE BEFORE INSERT POSITION 0 as begin if (new.id is null) then new.id = gen_id(gen_logs_id,1); end ^ CREATE OR ALTER TRIGGER LOGS_BI_IP FOR LOGS ACTIVE BEFORE INSERT POSITION 0 as begin -- -- Вставка IP вносившего изменение -- select rdb$get_context('SYSTEM', 'CLIENT_ADDRESS') from rdb$database into NEW.a_ip; end ^ SET TERM ; ^ COMMENT ON TABLE LOGS IS 'Лог справочников. Для фиксирования изменений в таблицах где есть primary key(id)'; COMMENT ON COLUMN LOGS.TNAME IS 'Имя таблицы - источника'; COMMENT ON COLUMN LOGS.FNAME IS 'Имя поля в таблице-источнике'; COMMENT ON COLUMN LOGS.ID_SRC IS 'Первичный ключ записи в таблице-источнике'; COMMENT ON COLUMN LOGS.A IS 'Action (I/U/D)'; COMMENT ON COLUMN LOGS.VAL IS 'Новое значение в логируемом поле'; COMMENT ON COLUMN LOGS.VAL_OLD IS 'Старое значение в логируемом поле'; COMMENT ON COLUMN LOGS.A_DT IS 'Дата-время изменения'; COMMENT ON COLUMN LOGS.A_USER IS 'Кто изменил'; COMMENT ON COLUMN LOGS.A_IP IS 'С какого IP было изменение'; COMMENT ON COLUMN LOGS.A_EXE IS 'Из какой программы были изменения.'; А на таблицах которые нужно логировать делается такого плана триггеры. Тест триггера получается широковат, но если строки заворачивать то очень сильно страдает читаемость. В нормальном редакторе или в IBExpert на мониторе FullHD получается вполне удобно. ID, понятное дело, в этих таблицах не меняется, просто я не стал делать исключение для этого поля. SET TERM ^ ; CREATE OR ALTER TRIGGER SPUB_AIUD_LOGS FOR SPUB ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0 as declare variable vtname varchar(31); declare variable va char(1); declare variable vid_src integer; begin -- -- Логирование изменений -- if (gen_id(GEN_SW_LOGS_SPUB, 0) = 0) then exit; -- vtname = 'SPUB'; -- if (inserting) then begin va = 'I'; vid_src = new.id; end else if (updating ) then begin va = 'U'; vid_src = old.id; end else if (deleting ) then begin va = 'D'; vid_src = old.id; end else begin va = '?'; vid_src = null; end -- -- обработка полей -- if ((updating and new.id is distinct from old.id ) or inserting or deleting) then insert into logs(tname, fname, a, id_src, val_old, val) values(:vtname, 'ID' , :va, :vid_src, old.id , new.id ); if ((updating and new.name is distinct from old.name ) or inserting or deleting) then insert into logs(tname, fname, a, id_src, val_old, val) values(:vtname, 'NAME' , :va, :vid_src, old.name , new.name ); -- end ^ SET TERM ; ^ В программе в контекстном меню справочников есть пункт "История" - вызываем стандартное окошко просмотра лога, передавая ему в параметре ID и название таблицы. В самом окошке, если интересует история конкретного поля, можно дополнительно зафильтровать. Для примера взят очень простой справочник, а есть такие где например 50 полей. Триггер увеличивается, главное не забыть при модификации таблицы поменять и триггер. Т.к. у меня все базы одинаковой структуры, а логирование не везде имеет смысл - то сделано отключение логирования, через значения в соответствующем генераторе. Способ не очень корректный т.к. доступ к генераторам есть у всех. Т.к. лог растет довольно быстро, я примерно раз в год делаю выгрузку старых записей во внешнюю базу архивов логов, оставляя в рабочей базе логов за последние 2 года. В окне просмотра лога есть возможность посмотреть историю как из рабочей так и из архивной базы логов. Из минусов - все значения приведены к строке, не поддерживаются блобы. Но на практике это мне еще ни разу не мешало.
Еще ведутся логи коннектов, лог печати документов, лог экспорта в бухгалтерию, лог изменения остатков, лог запросов от информационных киосков и т.п. Это уже все разной конструкции логи.
@fraks Володя, спасибо. Как всегда, основательно Есть, над чем подумать @Старый Плюшев С целью кто и что удалил из данных, если что Вообще-то, в этот раз я спланировал архитектуру так, что записи физически не удаляются, а помечаются "удаленными" (физически удалить их может только DBA). А логи только помогут найти виновных. Просто есть пару заказов от мелких клиник, там потеря данных критична @hvlad У меня как раз есть желание избежать велосипедостроительства. И твои дельные советы оказали бы мне более существенную помощь, чем сарказм
Док писал(а) Tue, 06 September 2022 13:35 в этот раз я спланировал архитектуру так, что записи физически не удаляются, а помечаются "удаленными" А ты уже спланировал архитектуру так, чтобы каждый пользователь ходил под собственным логином и никто не мог работать под соседским?..
Док Вообще-то, в этот раз я спланировал архитектуру так, что записи физически не удаляются, а помечаются "удаленными" (физически удалить их может только DBA). А логи только помогут найти виновных. Просто есть пару заказов от мелких клиник, там потеря данных критична там где помечаешь запись "удалённой", там же и помечай КТО и КОГДА. я же показывал как. полное логгирование всего и вся в большинстве случаев нафиг не нужно.