Структура базы данных для отслеживания истории изменений - PullRequest
9 голосов
/ 27 сентября 2008

Я работаю над проектами баз данных для системы управления проектами как с личным проектом, и я столкнулся с проблемой.

Я хочу внедрить систему заявок и хочу, чтобы билеты выглядели как билеты в Trac . Какую структуру я бы использовал для репликации этой системы? (У меня не было успеха при установке trac на любую из моих систем, поэтому я действительно не вижу, что он делает)

Примечание: я не заинтересован в попытке сохранить или отобразить билет в любой версии. Мне нужна только история изменений. Я не хочу хранить дополнительные данные. Кроме того, я реализовал такую ​​функцию, используя сериализованный массив в текстовом поле. Я не хочу реализовывать это как решение когда-либо снова.

Редактировать: я ищу только структуры баз данных. Триггеры / обратные вызовы на самом деле не проблема.

Ответы [ 6 ]

15 голосов
/ 27 сентября 2008

Я реализовал чистые данные об изменении записи, используя «тонкий» дизайн:

RecordID  Table  Column  OldValue  NewValue
--------  -----  ------  --------  --------

Возможно, вы не захотите использовать «Таблица» и «Столбец», а скорее «Объект» и «Свойство» и т. Д., В зависимости от вашего дизайна.

Преимущество заключается в гибкости и простоте за счет скорости запросов - кластеризованные индексы в столбцах «Таблица» и «Столбец» могут ускорять запросы и фильтры. Но если вы собираетесь просматривать журнал изменений в Интернете часто на уровне таблицы или объекта, возможно, вы захотите создать что-то более плоское.

РЕДАКТИРОВАТЬ : несколько человек справедливо отметили, что с этим решением вы не сможете собрать набор изменений. Я забыл об этом в приведенной выше таблице - у реализации, с которой я работал, также была таблица «Транзакция» с датой времени, пользователем и другой информацией, а также столбец «TransactionID», поэтому дизайн будет выглядеть так:

CHANGE LOG TABLE:
RecordID  Table  Column  OldValue  NewValue  TransactionID
--------  -----  ------  --------  --------  -------------

TRANSACTION LOG TABLE:
TransactionID  UserID  TransactionDate
-------------  ------  ---------------
3 голосов
/ 27 сентября 2008

Я сделал что-то подобное. У меня есть таблица с именем LoggableEntity, которая содержит: ID (PK).

Тогда у меня есть таблица EntityLog, которая содержит информацию об изменениях, внесенных в loggableentity (запись): ID (PK), EntityID (от FK до LoggableEntity.ID), ChangedBy (имя пользователя, который внес изменение), ChangedAt (smalldatetime, когда изменение произошло), Тип (перечисление: Создать, Удалить, Обновить), Детали (поле с записью, что изменилось - может быть XML с сериализованными деталями).

Теперь каждая таблица (сущность), которую я хочу отслеживать, «получена» из таблицы LoggableEntity, что означает, например, что у Customer есть таблица FK для таблицы LoggableEntity.

Теперь мой код DAL заботится о заполнении таблицы EntityLog каждый раз, когда вносятся изменения в запись клиента. Каждый раз, когда он видит, что класс сущности является loggableentity, он добавляет новую запись изменения в таблицу entitylog.

Итак, вот моя структура таблицы:

+------------------+           +------------------+
| LoggableEntity   |           | EntityLog        |
| ---------------- |           | ---------------- |
| (PK) ID          | <--+      | (PK) ID          |
+------------------+    +----- | (FK) LoggableID  |
        ^                      |      ...         |
        |                      +------------------+
+------------------+
| Customer         |
| ---------------- |
| (PK) ID          |
| (FK) LoggableID  |
|      ...         |
+------------------+
3 голосов
/ 27 сентября 2008

Вы после механизма базы данных, как это?

   CREATE OR REPLACE TRIGGER history$yourTable
        BEFORE UPDATE ON yourTable
        FOR EACH ROW
        BEGIN
            INSERT INTO
                history
            VALUES
                (
                :old.field1,
                :old.field2,
                :old.field3,
                :old.field4,
                :old.field5,
                :old.field6
                );
        END;
    /
    SHOW ERRORS TRIGGER history$yourTable
2 голосов
/ 27 сентября 2008

Что касается хранения большого количества дополнительных данных, я не могу придумать хороших способов сделать это. Вы должны хранить каждую ревизию, чтобы увидеть изменения.

Вот одно решение, которое я видел, хотя я не уверен, что оно лучшее. Имейте первичный ключ, скажем id, который указывает на конкретную ревизию. также есть поля ticket_number и revision_date. ticket_number не меняется, когда вы пересматриваете билет, но id и revision_date делают. Затем, в зависимости от контекста, вы можете получить конкретную ревизию или последнюю ревизию определенного тикета, используя groupwise max .

1 голос
/ 27 сентября 2008

Я бы сказал, создайте некоторый класс прослушивания событий, который вы пингуете каждый раз, когда что-то происходит в вашей системе и помещает описание события в базу данных.

Он должен хранить основную информацию о том, кто / что / где / когда / какую информацию.

сортировка по этой таблице событий проекта даст вам необходимую информацию.

0 голосов
/ 27 сентября 2008

Одним из возможных решений является сохранение копии заявки в таблице истории с пользователем, который внес изменение.

Однако, это будет хранить много дополнительных данных и потребует много обработки для создания представления, которое показывает Trac.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...