Как удобнее вести журналирование изменений?

Zmeishe
Дата: 03.10.2005 12:25:06
Т.е. как должна выглядеть LOG таблица, чтобы удобно было работать? Впоследствии визуализировать в DBGrid`е для бестолковых юзеров или распечатать.
Оригинал
IDNAME
1Вася
2Вова
3Дима


Варианты LOG таблицы
Вариант 1 На каждую таблицу создавать свою LOG таблицу такой структуры
IDNEW_NAMEOLD_NAMEOPERATIONUPDATE_DATEUPDATE_USER
1ВасяПетяUPDATE
1ПетяМаняUPDATE
4 МаняDELETE

Вариант 2 На каждую таблицу создавать свою LOG таблицу такой структуры
IDOLD_NAMEOPERATIONUPDATE_DATEUPDATE_USER
1ПетяUPDATE
1МаняUPDATE
1МаняDELETE

Вариант 3 На все таблицы одна LOG таблица
То, что предлагет IBExpert.
Там четыре таблицы и рулятся через триггеры.
CREATE TABLE IBE$LOG_TABLES (
    ID          INTEGER NOT NULL,
    TABLE_NAME  VARCHAR(31) NOT NULL,
    OPERATION   VARCHAR(1) NOT NULL,
    DATE_TIME   TIMESTAMP NOT NULL,
    USER_NAME   VARCHAR(31) NOT NULL
);
CREATE TABLE IBE$LOG_FIELDS (
    LOG_TABLES_ID  INTEGER NOT NULL,
    FIELD_NAME     VARCHAR(31) NOT NULL,
    OLD_VALUE      VARCHAR(255),
    NEW_VALUE      VARCHAR(255)
);
CREATE TABLE IBE$LOG_KEYS (
    LOG_TABLES_ID  INTEGER NOT NULL,
    KEY_FIELD      VARCHAR(31) NOT NULL,
    KEY_VALUE      VARCHAR(255)
);
CREATE TABLE IBE$LOG_BLOB_FIELDS (
    LOG_TABLES_ID   INTEGER NOT NULL,
    FIELD_NAME      VARCHAR(31) NOT NULL,
    OLD_CHAR_VALUE  VARCHAR(32000),
    NEW_CHAR_VALUE  VARCHAR(32000),
    OLD_BLOB_VALUE  BLOB SUB_TYPE 0 SEGMENT SIZE 80,
    NEW_BLOB_VALUE  BLOB SUB_TYPE 0 SEGMENT SIZE 80
);
Естественно перед визуализацией удобнее выборку привести к варианту 1.
А как выгоднее хранить, чтобы потом самому не запутаться и на выборки из логов жутких алгоритмов не писать?
VF
Дата: 03.10.2005 12:30:00
то что предлагает IBExpert лично для меня приемлемо, по его таблицам я делал и просмотр и поиск изменений (по дате, по типу, по пользователю и по таблице), так же делал и откат изменений, одно НО, при откате создавались записи в логах дополнительно, но это решаемо, если делать откат только одним пользователем (или даже завести пользователя только для откатов, видно будет что откатывали и когда).
правда есть одна заковыка, я сделал восстановление без учёта ссылочной целостности, то есть такой учёт производится самим восстанавливающим
AndreyK
Дата: 07.10.2005 17:09:14
Хм... Имея в руках только IBConsole я когда-то сделал примерно так как предлогает IBExpert :)

create table LOG_OPERATION
( // таблица в которой каждая запись идентифицируется с одной операцией над одной записью в журналируемой таблице
  OPERATIONKEY      INTEGER not null, // PK
  OPERATIONBLOCKKEY INTEGER not null, // FK на вышестоящюю таблицу
  OPERATIONTYPE     INTEGER not null, // тип операции
  TABLENAME         VARCHAR(31) not null, // имя таблицы
  PKVALUE           INTEGER not null // значение первичного ключа для записи в TABLENAME
);

create table LOG_UPD
( // таблица в которой каждая запись идентифицируется с изменением одного поля
  UPDKEY       INTEGER not null, // PK
  OPERATIONKEY INTEGER not null, // FK на LOG_OPERATION
  FIELDNAME    VARCHAR(31) not null, // имя поля которое менялось
  OLDVAL       VARCHAR(255) // старое значение
)

Да, не скажу, что такой лог очень удобно выводить в грид, но зато он не избыточен в плане занимаемого места как в случае с OLD_VALUE и NEW_VALUE (кстати с ними у меня было сделано в самой первой версии журнала :)) Имея цепочку значений начиная с самого старого (самое новое имеется в поле саой журналируемой таблицы, по этому его незачем хранить в журнале) можем проследить всю историю жизни записи. Гы, вспомнилось что так работает сегмент отката :)

Поддерка лога осуществляется триггерами, триггеры автоматически перегенеряются на основе метаданных, все цветет и пахнет, жизнь прекрасна.
Единственное условие которое сия система требует - это сурогатный ПК на все журналируемые таблицы и этот ключ не должен менятся во время всего цикла жизни записи. Но я не думаю, что это такая уж неприятнось :)
А с блобами... ну незнаю, думаю для них можно завести еще одну таблицу аля LOG_UPD.