Подтвердить что ты не робот

Какая лучшая архитектура для отслеживания изменений полей на объектах?

У нас есть веб-приложение, которое построено поверх базы данных SQL. Несколько различных типов объектов могут добавлять к ним комментарии, и некоторые из этих объектов нуждаются в отслеживании на уровне поля, подобно тому, как отслеживаются изменения полей в большинстве систем отслеживания ошибок (например, статус, назначение, приоритет). Мы хотели бы показать, кто изменился, каково было предыдущее значение и какое новое значение.

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

Однако насколько быстро эти данные могут расти, это лучшая архитектура? Каковы некоторые методы, обычно используемые для добавления этого типа функциональности в уже широкомасштабное приложение?

[ Изменить] Я начинаю щедрость по этому вопросу в основном потому, что я хотел бы узнать, в частности, что такое лучшая архитектура с точки зрения обработки масштаба очень хорошо. Ответ Тома Х. информативен, но рекомендуемое решение кажется довольно неэффективным по размеру (новая строка для каждого нового состояния объекта, даже если многие столбцы не изменились), и это невозможно, учитывая требование, чтобы мы могли отслеживать изменения и для созданных пользователем полей. В частности, я, вероятно, согласен с ответом, который может объяснить, как это реализовано в общей системе отслеживания проблем (JIRA или аналогичной).

4b9b3361

Ответ 1

Для этого есть несколько вариантов. У вас могут быть таблицы аудита, которые в основном отражают базовые таблицы, а также включают дату/время изменения, тип изменения и пользователь. Их можно обновить с помощью триггера. Это решение, как правило, лучше для аудита за кулисами (IMO), а не для решения специфического для приложения требования.

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

Третий вариант (который был бы моим первоначальным выбором с предоставленной информацией) состоял бы в том, чтобы иметь отдельную таблицу исторических изменений, которая обновляется через приложение и включает в себя PK для каждой таблицы, а также столбцы (столбцы), которые вы будет отслеживать. Он немного отличается от первого варианта того, что приложение будет отвечать за обновление таблицы по мере необходимости. Я предпочитаю это по первому варианту в вашем случае, потому что у вас действительно есть бизнес-требование, которое вы пытаетесь решить, а не техническое требование, например, аудит. Полагая логику в приложении, вы обладаете большей гибкостью. Возможно, некоторые изменения вы не хотите отслеживать, потому что они являются обновлениями обслуживания и т.д.

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

Итак, у вас может быть:

Problem_Ticket (ticket_id, имя_каталога) Problem_Ticket_History (ticket_id, change_datetime, описание, комментарий, имя пользователя)

В качестве альтернативы вы можете использовать:

Problem_Ticket (ticket_id, имя_каталога) Problem_Ticket_Comments (ticket_id, change_datetime, комментарий, имя пользователя) Problem_Ticket_Statuses (ticket_id, change_datetime, status_id, имя пользователя)

Ответ 2

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

Я бы лично просто создал одну таблицу с некоторыми столбцами метаданных об изменении и столбец, в котором хранится xml сериализованной версии старого объекта или того, что вам нужно. Таким образом, если вы хотите показать историю объекта, вы просто получите все старые версии и повторно увлажните их и сделайте. Одна таблица, чтобы управлять всеми ними.

Одним из часто забываемых решений будет использование Изменить сбор данных. Это может дать вам больше экономии пространства/производительности, если вы действительно заинтересованы.

Удачи.

Ответ 3

Это зависит от ваших точных требований, и это может быть не для вас, но для общего аудита в базе данных с помощью триггеров (так что интерфейс интерфейса и даже интерфейс интерфейса SP не имеют значения), мы используем AutoAudit, и он работает очень хорошо.

Ответ 4

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

Создайте свою аудиторскую модель, как показано ниже.


  ----------------  1      *  ------------                       
 | AuditEventType |----------| AuditEvent |                      
  ----------------            ------------                       
                                | 1    | 1                       
                                |      |                         
               -----------------        -------------            
              | 0,1                                  | +         
    -------------------                       ----------------   
   | AuditEventComment |                     | AuditDataTable |  
    -------------------                       ----------------   
                                                     | 1         
                                                     |           
                                                     |           
                                                     | +         
          -----------------  +             1  --------------     
         | AuditDataColumn |------------------| AuditDataRow |   
          -----------------                   --------------     



.

AuditEventType

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

.

AuditEvent

Содержит информацию о конкретном, даже если это действие вызвано этим действием.

.

AuditEventComment

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

.

AuditDataTable

Содержит список одной или нескольких таблиц, на которые повлиял соответствующий AuditEvent

.

AuditDataRow

Содержит список одной или нескольких идентификационных строк в соответствующем AuditDataTable, на который повлиял соответствующий AuditEvent

.

AuditDataColumn

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

.

AuditBuilder

Внедрить AuditBuilder (шаблон Builder). Создайте его в начале события и сделайте его доступным в контексте запроса или передайте его вместе с другими DTO. Каждый раз в любом месте вашего кода вы вносите изменения в свои данные, вызывайте соответствующий вызов в AuditBuilder, чтобы уведомить об этом изменения. В конце вызовите build() в AuditBuilder, чтобы сформировать выше структуру, а затем сохранить ее в базе данных.

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

Ответ 5

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

Лично я бы исследовал что-то вроде этого:

Создать AuditTable. У этого есть ID, номер версии, идентификатор пользователя и поле clob.

  • Когда объект # 768795 создан, добавьте строку в AuditTable со значениями: Id = # 768795 Версия: 0 Пользователь: (идентификатор пользователя, создавшего новый объект) clob: xml-представление всего объекта. (если пространство является проблемой, и доступ к этой таблице нечасто, вы можете использовать blob и "zip" представление xml на лету).

Каждый раз, когда вы что-то меняете, создавайте новую версию и сохраняете весь объект "сериализован" как XML Если вам нужно создать журнал аудита, у вас есть все, что вам нужно, и вы можете использовать простые инструменты или библиотеки для сравнения текста, чтобы увидеть, что изменилось во времени (что-то вроде Википедии).

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

Ответ 7

Я думаю, что Observer - идеальный образец в этом сценарии.