Структура базы данных для отслеживания истории изменений

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

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

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

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

6 ответов


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

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

вы можете не использовать "таблицу" и "столбец", а скорее "объект" и "свойство" и т. д., В зависимости от вашего дизайна.

это имеет преимущество гибкости и простоты, за счет скорости запроса-кластеризованные индексы в Столбцах "таблица" и "столбец" могут ускорить запросы и фильтры. Но если вы собираетесь часто просматривать журнал изменений в интернете за столом или уровень объекта, вы можете конструировать что-то более плоское.

редактировать: несколько человек справедливо отметили, что с помощью этого решения вы не можете собрать набор изменений. Я забыл об этом в таблице выше-реализация, с которой я работал, также имела таблицу " транзакция "с datetime, user и другой информацией и столбец" TransactionID", поэтому дизайн будет выглядеть так:

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

TRANSACTION LOG TABLE:
TransactionID  UserID  TransactionDate
-------------  ------  ---------------

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

   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

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

тогда у меня есть таблица EntityLog, что содержит сведения об изменениях, внесенных в loggableentity (записи): удостоверение личности (ПК), значением EntityId (ФК в LoggableEntity.ИД), ChangedBy (имя пользователя, который внес изменение), ChangedAt (типа smalldatetime когда произошло изменение), типа (enum: создание, удаление, обновление), реквизиты (поля Memo, содержащим что изменилось - может быть XML с сериализованным подробная информация.)

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

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

вот мой стол структура:

+------------------+           +------------------+
| LoggableEntity   |           | EntityLog        |
| ---------------- |           | ---------------- |
| (PK) ID          | <--+      | (PK) ID          |
+------------------+    +----- | (FK) LoggableID  |
        ^                      |      ...         |
        |                      +------------------+
+------------------+
| Customer         |
| ---------------- |
| (PK) ID          |
| (FK) LoggableID  |
|      ...         |
+------------------+

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

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


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

Он должен хранить основную информацию who/what/where/when / what.

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


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

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