Ведение истории изменений данных в базе данных

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

  • В среднем слое с использованием кода:. Этот подход позволит вам сохранить изменения в другой базе данных и, возможно, снять нагрузку с базы данных. Тем не менее, программист 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

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

Ответ 2

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

 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/

Ответ 3

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

MSDN - Аудит в SQL Server 2008

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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