Мені справді потрібні тригери для реляційної бази даних, наприклад, PostgreSQL?


10

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

Наприклад, ми зберігаємо клієнтів і хочемо виконати певну перевірку, яку неможливо зробити легко на рівні DDL. https://severalnines.com/blog/postgresql-triggers-and-stored-function-basics

Інший приклад - аудит.

Оновлення

Як працюють тригери та транзакції бази даних. Наприклад, якщо я хотів би виконати перевірку вставлених даних. Це робиться всередині транзакції. Що відбувається раніше: транзакція здійснена або виконується тригер?


However, why not perform validation of data on the application side before storing them into the database?ну ці двоє не є взаємовиключними. Цілком імовірно, ви будете перевіряти різні речі з обох сторін. Хоча перевірки на стороні програми орієнтовані на бізнес, проте перевірки на базі даних більш орієнтовані на дані. Подумайте в базі даних, що подається кількома і різними програмами.
Лаїв

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

Ваше оновлення повинно бути питанням самостійно, можливо, так, але на ваше запитання вже є відповідь про Database Administrators.SE . Коротше кажучи, навіть тригер "після оновлення" виконується до здійснення транзакції, і якщо виняток потрапить всередину тригера, це спричинить відкат.
Doc Brown

@GregBurghardt У більшості баз даних є заяви, які можна використовувати для відключення тригерів для таких видів діяльності.
Blrfl

1
@Blrfl: Так, але вам потрібно знати, що ці тригери можуть бути тимчасово відключені для всіх підключених користувачів, коли ви хочете лише умовно відключити ці перевірки для поточного сеансу.
Грег

Відповіді:


12

Це залежить від того, яку систему додатків ви будуєте:

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

    Основна перевага цього полягає в тому, що вам не доведеться розподіляти ділову логіку між додатком та db, тому підтримувати та розвивати систему стає часто простіше. Як бонус, ви не надто прив'язуєте програму до конкретного типу СУБД чи постачальника СУБД. Цей підхід, очевидно, необхідний, якщо ваша програма хоче мати можливість використовувати легку систему БД, яка не забезпечує тригери.

  • Якщо ж ви створили систему, де багато різних додатків мають спільну базу даних, і вона не може заздалегідь передбачити, які додатки напишуть їй у майбутньому, або які команди розроблятимуть додатки для заповнення даних у db у майбутньому, тоді це Краще ваша база даних несе відповідальність за забезпечення максимальної узгодженості даних. І саме тут спрацьовують тригери. У великих системах референс-обмеження часто для цього недостатньо, але тригер, який викликає збережену процедуру, може реалізувати практично будь-який вид валідації, який вам потрібен.

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

Дивіться також цю старішу публікацію SE: Логіка застосунків проти тригерів DB для очищення бази даних

Тож вирішіть для себе, яку систему ви будуєте, тоді ви можете прийняти обґрунтоване рішення, якщо тригери є правильним інструментом для вашої справи чи ні.


3

Думаю, питання полягає у відповідальності за якість даних.

Відповідь залежить від того, як ви бачите систему.

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

І навпаки, базу даних можна вважати складною формою файлів, яка знаходиться під безпосереднім і повним контролем програми. У цьому сенсі база даних перетворюється на чистий інструмент для серіалізації та навігації по документах. Він може надати деяку розширену поведінку для підтримки запитів та обслуговування документів (як, наприклад, JSON чи XML-інструменти), але знову ж таки цього не потрібно (як це робить більшість файлових потоків). У цьому випадку суто відповідальність програм за підтримку правильного формату та вмісту у файлі. У цьому перегляді є одна програма.

В обох поглядах наступне питання полягає в тому, як підтримувати використання бази даних як фантазійного файлу, або окремої служби. Ви можете досягти цього:

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

Кожен має свої плюси / мінуси і буде залежати від архітектурних обмежень середовища, в якому працює система.

Незалежно від того, яку точку зору ви вважаєте, завжди перевіряє дані на кордонах.

  • Перевірте поля в інтерфейсі користувача, який вводить користувач
  • Перевірте запит мережі / API, перш ніж він покине клієнта
  • Перевірте запит на мережу / API на сервері, перш ніж робити що-небудь
  • Перевірка даних, переданих у бізнес-правила
  • Перевірити дані, перш ніж зберігатись
  • Перевірте дані після отримання даних із збереження
  • так далі і так далі

Скільки валідації на кожному кордоні залежить від того, наскільки ризиковано його не підтвердити.

  • множення двох чисел разом?
    • ви зрозуміли неправильне число, це проблема?
  • викликати процедуру в заданому місці пам'яті?
    • Що в цьому місці пам'яті?
    • Що станеться, якщо об’єкта не існує або знаходиться в поганому стані?
  • використовуючи регулярний вираз на рядок, що містить кандзі?
    • Чи може модуль регулярного вираження обробляти unicode?
    • Чи може регулярний генекс обробляти unicode?

Централізація логіки перевірки хороша, але тривоги імхо не є хорошим способом її здійснення. Раніше я працював у системі, де декілька програм усі спільно використовували базу даних, з усією логікою перевірки та побічними ефектами, реалізованими в базі даних через тригери та збережені процедури. Я пішов з враженням, що краще мати мікросервіс перед базою даних і реалізувати всю логіку там. Нетривіальна логіка всередині бази даних SQL є антидіаграмою.
Joeri Sebrechts

1
@JoeriSebrechts Гаразд, я кусаю: чому нетривіальна логіка в базі даних є антипаттерном, і що робить її більш антиатлантичною, ніж введення її в окремо підтримувану програму?
Blrfl

@Blrfl Дві причини: API доступу до логіки в БД поступається API веб-сервісу (складніше версії, складніше у використанні, не легко кешується, ...), а бази даних ускладнюють чисто структурування та підтримку кодова база, розміщена всередині них. На мій досвід, простіше розмістити логіку у веб-службі перед базою даних, ніж всередині цієї бази даних.
Joeri Sebrechts

@JoeriSebrechts Я погоджуюся, що більшість платформ Database надають чудові інструменти для впровадження надійного, корисного та розвиваючого API. Багато в чому це запрошення відчути сильний біль. Моя думка полягала в тому, що мова йде про перспективу, усвідомлення того, що БД - це фантазійний файл, або що це справді окремий сервіс, приводить до наступного питання - як його обернути, щоб підтримати цей стиль використання. Я поясню свою відповідь, щоб бути зрозумілою з цього приводу.
Kain0_0

2

Ні, ніколи не слід використовувати тригери для перевірки.

База даних відповідає лише за власну цілісність. Ваша заявка повинна виконувати будь-якого користувача, що стикається з валідацією.

Бази даних виконують три рівні перевірки цілісності. Перший - перевірка рівня поля. Поле може бути необхідним, якщо немає значення (null), це помилка. Це також може бути обмеженням перевірки; домен має перелічену кількість значень.

По-друге, існують відносини між таблицями. В одній таблиці ви зберігаєте один або більше іноземних ключів, пов'язуючи цю таблицю з іншими таблицями і вимагаючи, щоб значення були дійсними ключами для "іншої таблиці". Подумайте про базу даних адрес, де ми підтримуємо адреси різних країн. Ключ країни в адресі повинен вказувати на відому країну. Чи достовірні дані (наприклад, поштовий індекс), це перевірка цілісності не стосується.

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

Валідація - це клопотання програми. Те, що німецький поштовий індекс складається лише з цифр, - це чек, який має зробити додаток, а не база даних. Рядок є тонким, тому вам може знадобитися подумати / обговорити в деяких випадках, якщо щось повинно бути тригером (захистити цілісність вашої бази даних) або в додатку (перевірка користувача перед валідацією).


Просто хотів додати, що якщо ОП потрібно додати правило перевірки acomplex, яке повинно бути в базі даних, він завжди може використовувати збережені процедури як більш безпечну альтернативу.
Борджаб

@Borjab: Можливо, перевірка як правильність роботи бази даних. Але користувач стикається з валідацією? №
Menno Hölscher

1
У вашій першій заяві сказано: "ніколи не використовуйте тригери для перевірки" , але нижче ви пишете: "так, ви можете використовувати тригери для певних типів перевірки, і не властиво, де провести лінію". Це читається досить суперечливо. Я рекомендую видалити ваше перше речення, це значно покращить вашу відповідь. О, і ваше останнє речення не відповідає на питання оновлення ОП, оскільки "до / після" не має нічого спільного з транзакцією. Я також рекомендував би видалити його. (дивіться мій коментар нижче питання щодо ОП).
Doc Brown

@DocBrown Відмінність полягає у захисті бази даних від корупції та перевірці користувачем. Тож у "будь-якій подальшій валідації" я посилаюся на перевірку користувача, яка стикається. Як я міг зробити це розрізнення більш чітким? Для початку я зняв "далі".
Menno Hölscher

2
Цілком чудово робити перевірку в базі даних. Так само, як це добре робити в додатку. Обидва мають свої переваги. Здійснення валідації в додатку означає, що ви повинні бути дуже обережними щоразу, коли ви запускаєте SQL без вашого ORM, який потрібен майже для кожного складного додатка.
Qwertie

1

Аудит - класичний приклад ефективного використання тригерів. Я виявив деякі помилки, допущені тестером (переміщення клієнта з одного рівня обслуговування на інший) завдяки таблиці аудиту, яка була реалізована тригерами. Настійно рекомендую використовувати тригери для аудиту.

Перевірка може бути зроблена на рівні переднього кінця, але я бачив дивні помилки в базі даних, які я обробляв (люди, які народилися в 3000 і т. Д.), І оскільки деякі з них я зробив сам, настійно рекомендую мати додатковий шар валідації в базі даних, про всяк випадок. Звичайно, цих типів помилок можна було б уникнути з обмеженнями перевірки, і багато разів вони ефективніші (в MS SQL вони є кращим методом; завжди перевіряйте документацію).


1

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

  1. Для аудиту, як описано в інших відповідях.
  2. Аудит у більш широкому розумінні: якщо змінено запис бази даних, тригер може записати подію для асихронної обробки даних, наприклад, нічний експорт до іншої програми.
  3. Тригери для переглядів: тригери можна визначити instead of. За допомогою цього засобу можна вставляти, оновлювати та видаляти записи з представлення даних. Тригери можуть поширювати ці дії на кілька таблиць. Це спосіб зробити доступне обмежене уявлення без викриття подробиць базових таблиць.
  4. Для явного збереження повороту бази даних: припустимо співвідношення N: M між таблицею A і B і проміжною таблицею R. Ви можете визначити обмеження зовнішніх ключів від R до A, а також B, вказавши, що запис у R слід відміняти, якщо його відповідний запис у B видалено. Однак бізнес-логіка іноді вимагає, щоб записи в A повинні мати хоча б одне відношення до запису в B. У цьому випадку тригер при видаленні R може допомогти застосувати цю логіку: якщо для запису в A останній запис у R видалено, то тригер може видалити А. У зоні, орієнтованій на додаток, потрібно щонайменше два обертання повороту. Це приклад для перевірки. Можливі й інші приклади: крім випадків використання (1), (2),
  5. Довіряйте: іноді адміністратори бази даних змінюють записи в командному рядку, не використовуючи вашу програму. Адміністратори ретельно працюють і знають, що вони роблять. Однак іноді вони можуть помилятися. Якщо консистенція є критичною, спрацьовує їх ремінь безпеки.

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

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