Використовувати БД тільки для складування даних — це все одно, що назвати Unix інтерфейсом для роботи з файлами. Тому, хочу нагадати про відомих і не дуже функції БД, які хотілося б частіше зустрічати в бойових веб-додатках.
tl;dr
Нижче буде про аутентифікацію користувачів, права доступу, цілісність даних, FDW, логування та статистику. Нічого нового.
Примітки
- Буду мати на увазі Ruby on Rails і Postgres, але більшість згадок добре нормально на інші мови і СУБД.
- Нічого нового не скажу, все це давно описано в документації і статтях. Просто хочу ще раз нагадати про інструменти і про те, куди їх можна застосувати, щоб життя стало трохи краще.
Peer/ident аутентифікація
Абсолютно чудова штука, яку майже ніхто не користується. Вона мапає користувача юнікса на користувача БД. У першому випадку мапає локального користувача, а в другому — віддаленого. Профіт в тому, що можна викинути з конфіга хост, логін і пароль (та й ім’я БД можна викинути), але все буде працювати як раніше. Плюс, буде зручніше заходити в консоль для прямого дебага (просто psql з терміналу замість усіх цих -h -U -W -d
і тд).
Документація PG про peer і про ident.
Нюанси: підходить, якщо у вас не тільки root і superuser на сервері; а у випадку з ident, ви контролюєте мережу, залізо і впевнені, що там немає засланців і саботажників.
Приклади використання
Безпека. Не можна потягти пароль від БД і підключитися до неї з локального оточення або ще звідки-небудь. Пароля немає і забирати нічого.
Розмежування доступу. Якщо на продакшн чи інший сервер є кілька ролей доступу і вони вже поділені на рівні unix-а, то до них зручно прив’язати і користувачів БД. В цьому випадку одна й та ж кодова база буде підключатися під різними користувачами БД. Наприклад, тех. підтримка і розробники лізуть в одну і ту ж rails console, але у одних вона readonly, а у других — повноцінна.
Права доступу
В Unix все про них думають і на роботу з-під root-а або на 'chmod 777'
дуже косо дивляться. А ось в БД все якось інакше. Superuser і в шлях. Хоча там всі не менш (а навіть більш) круто.
Там є ієрархія наслідування ролей (трохи схоже на group в юниксе), там є доступи різного рівня: до конкретних об’єктів (зразок прав доступу до файлів), до конкретних операторів (зразок правил sudoers
), навіть до конкретних рядками. Коротше, там все є. Користуйтеся.
Області додатки
У мінімальному варіанті, разом із вищезазначеними peer/ident можна розділити користувача для міграцій/деплоя і користувача для повсякденної роботи програми. Це, як мінімум, вбереже від виклику DDL в рантайме. Звичайно, є багато випадків модифікації структури БД “на гарячу”. Це і zero-downtime deploy, і різні хотфікси, і ребілди індексів з concurency (а іноді і без). Але, в загальному випадку, додаток DDL робити не повинен.
Ще варіант: якщо у вас “микросервисы”, але, чомусь, вони користуються однією БД, то явно розділити доступ до об’єктів БД — це дуже хороша ідея. Адже інтерфейси взаємодії повинні бути максимально локалізовані, а анархічний доступ до всіх даних сприяє розмивання логіки і відповідальності.
Обмеження цілісності
У Rails 5 хоч як почалася робота з reference і цілісністю даних. Але, в загальному випадку, багато розробники вважають, що валідації в моделі або її околицях цілком достатньо для збереження консистентного стану даних. На жаль, це зовсім не так.
Валідації можна пропустити, можна зайти безпосередньо в БД і навиконувати sql-я, можна при міграції накосячити. Загалом, багато чого можна зробити. Тому все, на що спирається бізнес-логіка має бути прибито констрейнтами в БД. Це єдиний спосіб зберегти цілісність даних і не отримати “сюрпризів” при черговому деплоі.
Foreign Data Wrapper
Це про підключення однієї БД до іншої БД, щоб отримати доступ до віддалених таблиць як до своїх власних. Головний профіт в тому, що веб-додаток тут ніяк не бере участь, зате є багато оптимізацій, при роботі двох однакових БД (взагалі, pushdown є для різних адаптерів, але там все складно, тому простіше вважати, що зв’язка PG-PG працює добре, а все інше — як вийде).
Використання FDW
Замість конфігиу з координатами декількох БД у веб-додатку незрівнянно простіше залишити одне підключення до БД і розрулити все на рівні самої БД. Там же, сам собою вирішиться питання прав доступу і вибору об’єктів, до яких потрібен доступ.
Плюс до цього, в майбутньому можна замінювати external table на materialized view або просто table, але нічого не змінювати у веб-додатку.
А ще, можна підключатися до екзотики типу MS Access і зникають проблеми з обмеженнями на використання реляцій в моделях. Адже якщо у вас 2+ підключення, то джоин двох баз на рівні веб-додатка ви не зробите, хоча ORM (зокрема ActiveRecord) чесно спробує це зробити… і відвалиться. А на рівні БД це зробити можна, в деяких випадках, майже без оверхеда.
Логування
Про нього майже всі знають і всі використовують. Але на всяк випадок нагадаю: не соромтеся логіювати довгі запити. З коробки, PG, воно вимкнене. Треба потикати log_min_duration_statement
. Стосовно його значення є багато холіваров і, можливо, мене закопають, але для початку, дайте пару секунд. Так, якщо у вас великий додаток, ви навряд чи це читаєте і самі знаєте що робити, а якщо маленький, то вам ніколи розбиратися з невеликими гальмами і вас турбують тільки фатальні речі.
Так само пам’ятайте про N+1. БД вам про це нічого не скаже. Використовуйте сторонні інструменти. Наприклад, bullet і здоровий глузд.
Статистика
Потрібно пам’ятати що вона є і що вона може стухнуть. На перших порах все добре. Але з часом, звичайно, виходить наступне: швидкість зміни даних, приблизно, однакова, а розмір таблиці все більше. Отже, vacuum/analyze таблиці починає відбуватися все рідше і в якийсь момент планувальник починає промахуватися. У кращому випадку, запит потрапляє в вищезазначене логування, в гіршому — ви просто страждаєте і не розумієте чому. Загалом, дивіться у pg_stat_user_tables
і співставляйте дати вакууму/аналайза з навантаженням на таблиці.
А ще іноді можна використовувати статистику для зразкового count
. Знадобиться рідко, але досить влучно, бо PG не Oracle і count
для всієї таблиці виконується не за O(1), хоча дуже хочеться.
Кінець
Дякую, що прочитали.