Способи мати історію змін записів бази даних


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 db. Весь db зберігається в одному файлі. Api також підтримує віртуальну файлову систему, так що в основному ви можете організувати зберігання в будь-якому місці та в будь-якому форматі, просто відповідайте на операції читання та запису при певних зрушеннях файлів. Можливими додатками для цього можуть бути шифрування, стиснення тощо. Найкраще, що контейнерний шар не повинен нічого знати про бази даних, формат файлів sql або sqlite, просто підкоряйтесь зворотним викликам xRead та xWrite.

Однією з ідей було впровадити функцію машини часу. Отже, будь-яка операція xWrite зберігає кожен сегмент, який він буде перезаписаний в історію "скасувати", і користувач може вибрати дату в минулому, щоб побачити, що містить db (можливо, режим лише для читання). У мене поки немає робочого прикладу ( про це було обговорено в списку пошти sqlite), але, ймовірно, інші двигуни постачають VFS API, тому щось подібне можливо. Після його впровадження він повинен бути сумісним зі структурами баз даних будь-якої складності.


Як ви вважаєте, чи масштабується такий підхід для великих проектів?
matcauthon

Я думаю, що це може додати великі накладні витрати для великих змін даних (очевидно, оскільки кожна зміна повинна бути збережена, хоча стиснення для старішої версії може допомогти). Крім того, з точки зору вашої схеми, поки вона працює для двох таблиць, вона працює і для двадцяти.
Maksee

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

Я зараз роблю версію цього. для кожного запису я маю Вставлену дату, Змінену дату та булевий прапор Active Record. Для початкової вставки Вставлені та Змінені дати встановлені як "Тепер" () (цей приклад знаходиться в Access), а прапор "Активні записи" встановлено на true. потім, якщо я модифікую цей запис, я копіюю всю річ у нову запис, змінюючи поля (поля), якими користувач змінюється, я залишаю дату "Вставити" рівну оригіналу і змінюю "Модифіковану дату" на "Тепер" (). Потім я перевертаю прапор активного запису на оригінальний запис falseта на новий запис true. У мене також є поле для ModifiedRecordsParentID, де я зберігаю ідентичність оригінального запису.

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


Не потрібно ActiveRecordпрапора. Рядок MAX (*) завжди повинен бути поточним записом. Відновлення до попередньої версії просто знову вставляє згаданий рядок у таблицю.
інвертувати

Я не знав, як змусити вибрану роботу, але тепер, коли ти це називаєш, я думаю про це і маю ідею, хммм
Бред

Зазвичай MAX (ім'я стовпця) вибирає найбільше значення у стовпці таблиці. Щоб вибрати цілий ряд, select top 1 order by id descendingбуде зроблено просте .
інвертувати

Так, це працює для простого одного запису, але в моїй таблиці була збірка дочірніх записів, яку потрібно було б вибрати відразу, але можна було змінити індивідуально. Просто трохи складніше.
Бред

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.