У проекті, над яким я працюю, кожна зміна рядків у деяких таблицях бази даних повинна відслідковуватися для подальшого аудиту чи відката. Потрібно легко знайти, хто змінив рядок, з якої IP-адреси та коли, і зможе відновити попередню версію.
Аналогічну річ використовує, наприклад, Stack Exchange. Коли я змінюю чуже запитання, можна виявити, що я його змінив, і відкатати зміни.
Який загальний прийом використовується для зберігання кожної зміни об'єкта в базі даних , враховуючи, що моя поточна схема має в основному ті ж властивості (нижче), що і середній бізнес-додаток?
- Об'єкти мають відносно невеликий розмір: можуть бути,
nvarchar(1000)
наприклад, деякі , але не величезні крапки двійкових даних, які зберігаються безпосередньо на диску, і доступ до них безпосередньо, а не через Microsoft SQLfilestream
, - Завантаження бази даних є досить низькою, і вся база даних обробляється однією віртуальною машиною на сервері,
- Доступ до попередніх версій не повинен бути таким швидким, як доступ до останньої версії, але все ж повинен бути сучасним¹ і не надто повільним².
<tl-dr>
Я думав про наступні випадки, але у мене немає реального досвіду подібних сценаріїв, тому я почув би думку інших:
Зберігайте все в одній таблиці, розрізняючи рядки за ідентифікацією та версією. IMO, це серйозно нерозумно, і рано чи пізно зашкодить на рівні продуктивності. При такому підході також неможливо встановити інший рівень безпеки для останніх позицій та для відстеження версій. Нарешті, кожен запит було б складніше написати. Насправді, щоб отримати доступ до сучасних даних, я змушений був би згрупувати все за ідентифікатором та отримати в кожній групі останню версію.
Зберігайте останню версію в одній таблиці та при кожному зміні скопіюйте застарілу версію в іншу таблицю в іншій схемі. Недолік у тому, що кожного разу ми зберігаємо кожне значення, навіть якщо воно не змінювалося. Встановлення незмінних значень
null
не є рішенням, оскільки я також повинен відстежувати, коли значення змінюється наnull
або з ньогоnull
.Зберігайте останню версію в одній таблиці, а список змінених властивостей із попередніми значеннями - в іншій таблиці. Здається, є два недоліки: найважливішим є те, що єдиний спосіб сортування неоднорідних типів попередніх значень в одному стовпчику - це мати a
binary(max)
. Другий - це, я вважаю, було б складніше використовувати таку структуру під час показу попередніх версій користувачеві.Зробіть те саме, що і в двох попередніх пунктах, але зберігайте версії в окремій базі даних. З точки зору продуктивності, це може бути цікавим, щоб уникнути уповільнення доступу до останніх версій, якщо попередні версії були в тій самій базі даних; все-таки я вважаю, що це передчасна оптимізація, і її потрібно робити лише за наявності доказів того, що наявність старих і останніх версій в одній базі даних є вузьким місцем.
</tl-dr>
¹ Наприклад, було б неприпустимо зберігати зміни у файлі журналу, як це робиться для HTTP-журналів, і передавати дані з журналу в базу даних вночі, коли завантаження сервера найменше. Інформація про різні версії повинна бути доступною негайно або майже негайно; кілька секунд затримка прийнятна.
² До інформації не доступний дуже часто і лише певна група користувачів, але все-таки було б неприпустимо змушувати їх чекати 30 секунд, щоб список версій відобразився. Знову ж таки, кілька секунд затримка прийнятна.