Ведение истории изменений данных в базе данных - PullRequest
11 голосов
/ 23 декабря 2009

Каждое изменение данных в некоторой строке в базе данных должно сохранять данные предыдущей строки в некоторой истории, чтобы пользователь мог выполнить откат к предыдущему состоянию данных строки. Есть ли хорошая практика для такого подхода? Пробовал с DataContract и сериализацией и десериализацией объектов данных, но он становится немного запутанным со сложными объектами.

Итак, чтобы быть более ясным:

  1. Я использую NHibernate для доступа к данным и хочу остаться вне зависимости от базы данных (для тестирования с использованием SQL Server 2005)

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

Примером использования будет следующий:

  • У меня есть новостная статья
  • Кто-то вносит некоторые изменения в эту статью
  • Главный редактор видит, что в этой новости есть некоторые опечатки
  • Он решает выполнить откат к предыдущей действительной версии (пока не будет исправлена ​​последняя версия)

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

Ответы [ 7 ]

14 голосов
/ 23 декабря 2009

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

  • В базе данных с использованием триггеров: Я бы порекомендовал этот подход, потому что тогда нет никакой возможности изменить данные без создания записи. При этом вам необходимо учитывать 3 типа изменений: Добавить, Удалить, Обновить. Поэтому вам нужна функциональность триггера, которая будет работать на всех трех.

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

Управление не будет возвращено вызывающей программе, пока выполнение триггера не будет завершено. Поэтому вы должны держать код как можно более легким и быстрым.

  • На среднем уровне с использованием кода: Этот подход позволит вам сохранить изменения в другой базе данных и, возможно, снять нагрузку с базы данных. Однако программист SQL, выполняющий инструкцию UPDATE, полностью обойдет ваш средний уровень, и у вас не будет контрольного журнала.

Структура таблицы аудита

У вас будут следующие столбцы:
Autonumber PK, TimeStamp, ActionType + All columns from your original table
и я делал это в прошлом следующими способами:

Структура таблицы:
Autonumber PK, TimeStamp, ActionType, TableName, OriginalTableStructureColumns

Эта структура будет означать, что вы создаете одну таблицу аудита для каждой сохраненной таблицы данных. Сохранение и восстановление данных довольно легко сделать. Я бы порекомендовал этот подход. Имя Значение Пара:
Autonumber PK, TimeStamp, ActionType, TableName, PKColumns, ColumnName, OldValue, NewValue

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

5 голосов
/ 23 декабря 2009

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

MSDN - Аудит в SQL Server 2008

5 голосов
/ 23 декабря 2009

Вы можете использовать триггеры для этого. Вот один пример.

 AutoAudit is a SQL Server (2005, 2008)
 Code-Gen utility that creates Audit
 Trail Triggers with:

     * Created, Modified, and RowVerwsion (incrementing INT) columns to table
     * view to reconstruct deleted rows
     * UDF to reconstruct Row History
     * Schema Audit Trigger to track schema changes
     * Re-code-gens triggers when Alter Table changes the table

http://autoaudit.codeplex.com/

2 голосов
/ 23 декабря 2009

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

Например, если у вас есть таблица с именем "book", с столбцами "id", "name", "author", вы можете добавить таблицу с именем "book_version" с столбцами "id", "name", " автор "," версия_даты "," версия_пользователя "

Каждый раз, когда вы вставляете или обновляете запись в таблице «book», ваше приложение также будет вставляться в «book_version».

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

1 голос
/ 23 декабря 2009

Одним из способов является использование БД, которая поддерживает это изначально, например, HBase . Обычно я бы не предлагал «Измените сервер БД, чтобы получить эту единственную функцию», но, поскольку вы не указываете сервер БД в своем вопросе, я предполагаю, что вы подразумеваете это как открытый, и встроенная поддержка на сервере одна из лучших реализаций этой функции.

0 голосов
/ 09 мая 2012

Я очень хорошо решил эту проблему с помощью NHibernate.Enverse

Для тех, кто интересуется, прочитайте это: http://nhforge.org/blogs/nhibernate/archive/2010/07/05/nhibernate-auditing-v3-poor-man-s-envers.aspx

0 голосов
/ 23 декабря 2009

Какую систему баз данных вы используете? Если вы используете базу данных, совместимую с ACID (атомарность, согласованность, изоляция, долговечность), не можете ли вы просто использовать встроенную функцию отката для возврата к предыдущей транзакции?

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