Способы иметь историю изменений записей базы данных


21

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

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

Каковы их плюсы / минусы?


1
Что именно вы хотите версии? Схема или данные?
tdammers

1
Я хочу версии данных. Чтобы остановиться на примере cms, допустим, версии статей .
Matcauthon

Вы можете посмотреть в Datomic.
dan_waterworth

Ответы:


19

Существует два основных подхода: таблица аудита, в которой хранятся все предыдущие значения, или указание даты начала / окончания как части таблицы, и все обновления создают новую запись, закрывая старую.

Обновление: SQL SERVER 2016 поддерживает это как шаблон дизайна / тип таблицы - https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017.


4
Таким образом, первый подход может быть более масштабируемым. Поскольку доступ к «заархивированным» данным будет редко, дизайн базы данных может быть оптимизирован. И рабочий стол держится маленьким. В зависимости от сложности, также должно быть возможно сохранить только различия. Желательно ли использовать шаблон памяти ?
Matcauthon

1
Это будет зависеть от вашего использования, может быть достаточно использовать триггеры для заполнения таблиц и затем предоставить способ выбора того, что и как далеко откатить.
Jmoreno

В вашем ответе есть опечатка (шаблон должен быть шаблоном)
geocodezip

7

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

Каждая таблица, которую необходимо отслеживать, будет иметь два datetimeстолбца fromи to. Они начинаются со значения NULLв каждом (начало времени до конца времени). Когда вам нужно «изменить» строку, вы добавляете новую строку, и в то же время вы обновляете toв предыдущей строке до Nowи fromв строке, к которой вы добавляетеNow .

Для более подробной информации смотрите:

Этот метод призван AuditTrailуправлять устаревшими данными, и его история хранит историю изменений.

Похоже, вопрос такого рода уже опубликован:


К сожалению, этот вопрос, похоже, был удален :(
Дуглас Гаскелл

Нет проблем, вот ссылка . Еще одно хорошее дизайнерское предложение по ссылке
Юсубов

2

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

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

Каждая база данных имеет свой собственный способ записи и кодирования триггеров. Если вы используете SQLite, посетите SQLite.org для синтаксиса. Для других баз данных вы можете посетить их официальные сайты.


1

Вы, наверное, знаете о двигателе Sqlite . Вся БД сохраняется в одном файле. API также поддерживает виртуальные файловые системы, поэтому в основном вы можете организовать хранилище в любом месте и в любом формате, просто реагируя на операции чтения и записи при определенных смещениях файлов. Возможными приложениями для этого могут быть шифрование, сжатие и так далее. Самое приятное, что контейнерный уровень не должен ничего знать о базах данных, форматах файлов sql или sqlite, просто подчиняется обратным вызовам xRead и xWrite.

Одной из идей было реализовать функцию машины времени. Таким образом, любая операция xWrite сохраняет каждый сегмент, который она будет перезаписывать в истории «отмены», и пользователь может выбрать дату в прошлом, чтобы увидеть, что содержится в БД (возможно, только для чтения). Я не работаю уже пример еще (была дискуссия об этом в SQLite списке почты), но , возможно , другие двигатели поставляют VFS API , так что- то подобное возможно. И как только он будет реализован, он должен быть совместим со структурами базы данных любой сложности.


Как вы думаете, является ли этот подход масштабируемым для более крупных проектов?
Matcauthon

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

1

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

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

Затем у нас есть триггеры на вставку / обновление / удаление таблиц, которые мы хотим отслеживать.

Плюсы:

  • Все данные в одной таблице
  • Может быть настроен для отслеживания всех полей или определенных полей в таблице
  • Легко показать версии на каждом поле для таблицы

Минусы:

  • Наличие всей аудиторской информации в одной таблице приводит к чрезвычайно большому количеству записей
  • Нужно много триггеров

0

Я делаю версию этого сейчас. для каждой записи у меня есть дата вставки, дата изменения и логический флаг активной записи. Для начальной вставки даты Inserted и Modified установлены на Now () (этот пример в Access), а флаг активной записи установлен на true. затем, если я изменяю эту запись, я копирую все это в новую запись, изменяя поля, которые изменяет пользователь, я оставляю дату вставки равной оригиналу и изменяю дату изменения на Now (). Затем я переворачиваю флаг активной записи исходной записи в falseи новой записи в true. У меня также есть поле для ModifiedRecordsParentID, где я сохраняю идентичность исходной записи.

Тогда, если мне даже нужно запросить, я могу просто вернуть записи, где ActiveRecord = trueи я буду получать только самую последнюю информацию.


Нет необходимости для ActiveRecordфлага. Строка MAX (*) всегда должна быть текущей записью. Восстановление предыдущей версии просто вставляет указанную строку в таблицу снова.
инвертировать

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

Обычно MAX (column_name) выбирает наибольшее значение в столбце таблицы. Чтобы выбрать весь ряд, просто select top 1 order by id descendingподойдет.
инвертировать

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.