Кращий дизайн таблиці змінних даних / аудиту? [зачинено]


114

Мені потрібно створити таблицю бази даних для зберігання різних журналів змін / аудиту (коли щось було додано, видалено, змінено тощо). Мені не потрібно зберігати особливо детальну інформацію, тому я щось думав так:

  • id (для події)
  • користувач, який його спровокував
  • назва події
  • опис події
  • мітка часу події

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


Я читаю вашу відповідь і дивуюсь, що про Закон ніхто не говорить. Я знаю, що деякі законні документи чи документи, що відповідають правилам, пояснюють, як ми ПОВИННІ впровадити таблицю аудиту (лише для читання). Але я не маю більше інформації, ніж ця. Я просто знаю, що воно існує. Я думаю про аудиторський слід у CFR 21, частина 11.
Bastien Vandamme

Відповіді:


70

У проекті, над яким я працюю, журнал аудиту також почався з дуже мінімалістичного дизайну, як той, який ви описали:

event ID
event date/time
event type
user ID
description

Ідея була однаковою: щоб все було просто.

Однак швидко стало очевидним, що цього мінімалістичного дизайну недостатньо. Типовий аудит зводився до таких питань:

Who the heck created/updated/deleted a record 
with ID=X in the table Foo and when?

Отже, щоб можна було швидко відповісти на подібні запитання (використовуючи SQL), ми отримали два додаткові стовпці в таблиці аудиту

object type (or table name)
object ID

Ось тоді дизайн нашого журналу аудиту дійсно стабілізувався (ось уже кілька років).

Звичайно, останнє «покращення» працювало б лише для таблиць, які мали сурогатні ключі. Але вгадайте, що? Усі наші таблиці, які варто перевірити, мають такий ключ!


Єдина проблема, яка була у мене з цим дизайном (аудиторський слід на основі опису), - це локалізація мови, що використовується в цьому полі.
Сем Вілсон

@Sam Я не бачу такої проблеми, якщо повідомлення генерується системою, просто використовуйте тут ключ для рядка перекладу;
JCM

4
@Hiru: Коли ви "змішуєте" два чи більше різних поняття в один стовпець, то рано чи пізно це відбувається, як ніколи, задній випадок. Наприклад, якщо ви "змішуєте" тип події та тип об'єкта, це вплине на запити типу "показати мені записи для всіх об'єктів даного типу" та "показати мені записи для всіх подій даного типу" (запитів було б більше складний і, швидше за все, буде працювати набагато повільніше).
Ярику

3
На додаток до цих стовпців може бути додатковий стовпець для структурованого опису / корисного навантаження структурованих подій . У цьому стовпці містяться відомості про події (будь-якої складності) у читаному для комп'ютера форматі XML / JSON. Легко серіалізувати, запитувати проти (принаймні, у Postgres / MSSQL), міркувати про те.
turdus-merula

1
@ Бенджамін: відповідь є у доменній моделі (він же бізнес-модель). Якщо модель дозволяє одночасно створювати сутності (наприклад, як частину логічної транзакції), то я не бачу жодних проблем у тому, щоб мати кілька записів журналу з точно однаковою міткою часу. Наприклад, якщо створення замовлення на купівлю (як транзакції) може включати створення N елементів замовлення, то всі відповідні записи 1 + N журналу матимуть однакову мітку часу. Подальший аналіз такого журналу може скористатися цим, трактуючи ці записи 1 + N не як незалежні, а як елементи логічної транзакції. Сподіваюся, це має сенс.
Ярик

24

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

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


1
Це дуже добре. Я не розумію, чому люди ігнорують останні повідомлення.
Maddy.Shik

3
Пошук подій є альтернативним підходом до надання функцій відкоту при збереженні історії.
Сем

23

Є ще кілька речей, які ви хочете перевірити, такі як назви таблиць / стовпців, комп’ютер / додаток, за допомогою якого було зроблено оновлення тощо.

Тепер це залежить від того, наскільки детально аудит вам справді потрібен і на якому рівні.

Ми почали будувати власне аудиторське рішення на основі тригера, і ми хотіли перевірити все, а також маємо під рукою варіант відновлення. Це виявилося занадто складним, тому ми закінчили зворотну інженерію тригерного інструменту ApexSQL Audit на основі тригера, щоб створити власне власне рішення.

Поради:

  • Включити до / після значень

  • Додайте 3-4 стовпчики для зберігання первинного ключа (якщо це складений ключ)

  • Зберігайте дані за межами основної бази даних, як уже запропонував Роберт

  • Витратьте гідну кількість часу на підготовку звітів - особливо тих, які можуть знадобитися для відновлення

  • План збереження імені хоста / програми - це може стати дуже корисним для відстеження підозрілих дій


2
Чому б ви реверсували його, а не купували?
Джовен

1
більше контролю над продуктом
Tebe

1
Сподіваюся, вони не подали до вас позов.
сортувальник

9

Тут є багато цікавих відповідей та подібних питань. Єдине, що я можу додати з особистого досвіду:

  1. Помістіть свою таблицю аудиту в іншу базу даних. В ідеалі ви хочете відокремити від вихідних даних. Якщо вам потрібно відновити базу даних, ви не хочете відновити слід аудиту.

  2. Денормалізуйте якомога розумніше. Ви хочете, щоб таблиця мала якомога менше залежностей від початкових даних. Таблиця аудиту повинна бути простою і блискавично витягувати дані. Немає фантазійних приєднань або пошуку в інших таблицях, щоб отримати дані.


8
Чи справді ненормалізовані дані будуть швидше читати порівняно з нормалізованими даними з відповідними індексами? (Would не всі результат дублювання зчитувальних даних з HDD?)
Sam

4

Що ми маємо в нашій таблиці: -

Primary Key
Event type (e.g. "UPDATED", "APPROVED")
Description ("Frisbar was added to blong")
User Id
User Id of second authoriser
Amount
Date/time
Generic Id
Table Name

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


2
Що означає "сума"?
turdus-merula

Це фінансова заявка, тому це вартість долара речі, яка має дозвіл тощо.
WW.

4

Взагалі користувацький аудит (створення різних таблиць) - це поганий варіант. Тригери бази даних / таблиці можуть бути відключені, щоб пропустити деякі дії журналу. Спеціальні таблиці аудиту можуть бути підроблені. Можуть статися винятки, які принесуть заявку. Не згадуючи труднощів у розробці надійного рішення. Поки я бачу дуже прості випадки в цій дискусії. Вам потрібно повне відділення від поточної бази даних та від будь-яких привілейованих користувачів (DBA, Developers). Кожні основні RDBMS надають засоби аудиту, які навіть DBA не можуть вимкнути, підробляти таємницю. Отже, забезпечена можливість аудиту від постачальника RDBMS повинна бути першим варіантом. Іншим варіантом буде сторонній зчитувач журналів транзакцій або користувацький зчитувач журналів, який виштовхує розкладену інформацію в систему обміну повідомленнями, яка опиняється в деяких формах аудиту даних сховища або обробника подій у режимі реального часу. Підсумовуючи: Архітектор рішення / «Руки на архітектора даних» повинен залучати до призначення такої системи на основі вимог. Зазвичай це занадто серйозні речі, щоб просто передати розробникам рішення.


3

Існує багато способів зробити це. Мій улюблений спосіб:

  1. Додати а mod_user поле у ​​свою вихідну таблицю (ту, яку потрібно ввійти).

  2. Створіть таблицю журналів, яка містить поля, які ви бажаєте ввійти, плюс a log_datetimeта seq_numполе. seq_numє первинним ключем.

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

Тепер у вас є запис про кожну зміну і хто її здійснив.


Отже ... що повинно робити поле mod_user?
conny

1
Скажіть, хто змінив. Код оновлення повинен містити щось для встановлення цього поля поточному користувачеві.
JosephStyons

Що тоді з делетами? Якщо ви видалите рядок, як обробляти значення для стовпця mod_user?
Кенн Кал

@KennCal Тригери можуть використовувати віртуальні таблиці, ви можете бачити дані після того, як і раніше, всередині того ж тригера. Не має значення операція. stackoverflow.com/questions/6282618/…
Ренан Кавалієрі

2
@KennCal Ви маєте рацію, тригер видалення повинен зберігати цю інформацію для вас. Чорт у деталях, однак - якщо ви використовуєте автентифікацію SQL, тригер може просто запустити [виберіть CURRENT_USER]. Якщо це клієнтська програма, тоді код клієнта повинен оголосити, хто це. Якщо це виклик API, то користувач, що видаляє, повинен бути обов'язковим параметром для виклику.
JosephStyons

1

За принципом поділу:

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

  2. Не використовуйте тригери для аудиту всієї бази даних, тому що у вас виникне безлад різних баз даних для підтримки. Вам доведеться написати один для DB2, SQLServer, Mysql тощо.

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