В проекте, над которым я работаю, каждое изменение строк в некоторых таблицах базы данных должно отслеживаться для дальнейшего аудита или отката. Должно быть легко найти, кто изменил строку, с какого IP-адреса и когда, и иметь возможность восстановить предыдущую версию.
Подобная вещь используется, например, Stack Exchange. Когда я изменяю чужой вопрос, можно обнаружить, что я его изменил, и откатить изменения.
Какой общий метод используется для хранения каждого изменения объекта в базе данных , учитывая, что моя текущая схема имеет в основном те же свойства (ниже), что и обычное бизнес-приложение?
- Объекты имеют относительно небольшой размер: это могут быть,
nvarchar(1000)
например, некоторые , но не огромные двоичные объекты двоичных данных, которые хранятся непосредственно на диске и доступны напрямую, а не через Microsoft SQLfilestream
, - Загрузка базы данных довольно низкая, и вся база данных обрабатывается одной виртуальной машиной на сервере,
- Доступ к предыдущим версиям не должен быть таким же быстрым, как доступ к последней версии, но все же должен быть актуальным и не слишком медленным2.
<ТЛ-дг>
Я думал о следующих случаях, но у меня нет никакого реального опыта с такими сценариями, поэтому я услышал бы мнения других:
Сохраните все в одной таблице, различая строки по идентификатору и версии. ИМО, это серьезно глупо и рано или поздно повредит уровню производительности. При таком подходе также невозможно установить другой уровень безопасности для последних элементов и трассировки версий. Наконец, каждый запрос будет сложнее написать. На самом деле, чтобы получить доступ к актуальным данным, я был бы вынужден сгруппировать все по идентификатору и получить в каждой группе последнюю версию.
Сохраните последнюю версию в одной таблице и при каждом изменении копируйте устаревшую версию в другую таблицу в другой схеме. Недостаток в том, что каждый раз мы храним каждое значение, даже если оно не изменилось. Установка неизмененных значений в
null
не является решением, так как я также должен отслеживать, когда значение изменяется наnull
или сnull
.Сохраните последнюю версию в одной таблице, а список измененных свойств с их предыдущими значениями - в другой таблице. Кажется, у этого есть два недостатка: самый важный из них заключается в том, что единственный способ сортировки разнородных типов предыдущих значений в одном столбце - это иметь
binary(max)
. Во-вторых, я полагаю, что было бы сложнее использовать такую структуру при отображении предыдущих версий пользователю.Сделайте то же самое, что и в двух предыдущих пунктах, но сохраните версии в отдельной базе данных. С точки зрения производительности, это может быть интересно, чтобы избежать замедления доступа к последним версиям, если предыдущие версии находятся в той же базе данных; тем не менее, я считаю, что это преждевременная оптимизация, и ее следует проводить только в том случае, если есть доказательство того, что наличие более старых и последних версий в одной и той же базе данных является узким местом.
</ ТЛ-дг>
¹ Например, было бы неприемлемо сохранять изменения в файле журнала, как это делается для журналов HTTP, и сбрасывать данные из журнала в базу данных ночью, когда нагрузка на сервер самая низкая. Информация о различных версиях должна быть доступна немедленно или почти сразу; задержка в несколько секунд приемлема.
² Доступ к информации осуществляется не очень часто и только определенной группой пользователей, но все же было бы недопустимо заставлять их ждать 30 секунд для отображения списка версий. Опять же, задержка в несколько секунд является приемлемой.