Какова лучшая архитектура для отслеживания изменений полей на объектах? - PullRequest
24 голосов
/ 25 января 2010

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

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

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

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

Ответы [ 7 ]

7 голосов
/ 25 января 2010

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

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

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

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

Итак, вы можете иметь:

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

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

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

4 голосов
/ 18 февраля 2010

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

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

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

Удачи.

1 голос
/ 18 февраля 2010

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

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



  ----------------  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, чтобы сформировать указанную выше структуру, а затем сохраните ее в базе данных.

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

1 голос
/ 25 января 2010

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

0 голосов
/ 16 июля 2012

Я знаю, что этот вопрос очень старый, но другая возможность, встроенная в SQL ИЗМЕНЕНИЯ В СЛЕДУЮЩЕЙ:

Вы можете найти больше информации по этой ссылке: Введение в сбор данных изменений (CDC) в SQL Server 2008 http://www.simple -talk.com / SQL / учиться-SQL-сервер / введение к изменению-данных Capture- (ЦКЗ) -в-SQL-сервер-2008 /

0 голосов
/ 10 февраля 2011

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

0 голосов
/ 19 февраля 2010

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

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

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

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

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

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

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