БД — это не только хранилище данных

Использовать БД только для складирования данных — это всё равно, что назвать 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), хотя очень хочется.

Конец

Спасибо, что прочитали. Если не сложно, ответьте на вопрос ниже. В свете недавней статьи про GQL вместо SQL он меня начал волновать особенно сильно.

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *