Взаимодействие компонента «Postgres» в web-фреймворке «Ruby on Rails»
Конференция: II Студенческая международная научно-практическая конференция «Молодежный научный форум»
Секция: Технические науки
II Студенческая международная научно-практическая конференция «Молодежный научный форум»
Взаимодействие компонента «Postgres» в web-фреймворке «Ruby on Rails»
«Ruby on Rails» («RoR») – быстроразвивающаяся система, которая находится в постоянном взаимодействии со многими языками программирования. Компонент «Postgres» является его неотъемлемой частью, точнее сказать, ядром, которое содержит в себе практически всю постоянную, переменно-изменяющуюся и поступающую в систему информацию. В данной статье будут рассмотрены некоторые особенности отладки, связанные с улучшением производительности базы данных (БД) в уже готовом или еще проектируемом Rails приложении [1].
1. Управление запросами с помощью таймаутов
Запросы (долгие и короткие) оказывают в какой-то мере негативное влияние на работу баз данных. Независимо от того, работают они минуту или несколько секунд – они несут за собой некоторые негативные эффекты, такие как блокировки, потребляют большое количество ресурсов, переполняют WAL. С помощью Postgres достаточно просто добиться большей стабильности при установки таймаутов на запросы. Можно установить значения по умолчанию (например, 5 секунд) или подобрать любое удобное время, по истечению которого процесс будет убит (листинг 1).
Листинг 1 – Установка общего таймаута для БД
Если вам нужно задать таймаут для отдельной сессии, то можно записать время для конкретного соединения (листинг 2).
Листинг 2 – Установка таймаута для текущего соединения
2. Поиск «плохих» (неисправных) запросов
RoR многое абстрагирует при работе с вашей базой данных. Это в каком-то смысле хорошо, но не всегда. Сам Postgres позволяет отслеживать все запросы, как короткие так и долгие, но по мере роста БД это может оказаться недостаточным. Чтобы узнать происхождение того или иного запроса существует интересный гем файл «Marginalia», который как бы управляет «логистикой запросов» [1]. В случае, если вы увидите неправильный путь запроса вы сможете его спокойно поправить или убрать вообще (листинг 3).
Листинг 3 – Управление «логистикой запроса»
3. Высокоуровневые обзоры запросов в базе данных
Часто разработчику необходимо видеть общую картину запросов, протекающих в его базе данных. Существует одно расширение в Postgres – «pg_stat_statement», которое предусматривает управление в облачной среде. Оно позволяет разработчику видеть, какие запросы выполняются с момента «отката» и как они себя ведут.
В листинге 4 представлен пример для вывода 10 последних долго выполняющихся запросов и определения их среднего времени.
Листинг 4 – Поиск последних долго выполняющихся запросов
Если запустить инструмент «track_io_timing» в Postgres, то можно выяснить, откуда идет причина задержек в обработке запросов (из самого процессора или устройств ввода-вывода).
4. Использование «продвинутых» инструментов в Postgres
По умолчанию в БД, которая создана на основе Postgres, имеется файл «schema.rb», в котором хранится копия схемы базы данных. Этот файл используют в основном при тестировании системы. Но к сожалению часто встречаются ошибки в тестировании, так как многие расширенные функции в Postgres (функциональные/частичные индексы), составленные в виде первичных ключей, не могут иметь представление в DSL [3, с.113].
Исправить это можно переходом на генерируемый Rails файл «structure.sql». Сделать это можно так, как представлено в листинге 5.
Листинг 5 – Переход на работу с файлом structure.sql
Как мы можем видеть, внутри файла используется такой же формат, как и на Postgres (pg_dunp) [2], который генерирует полностью восстановленную форму нашей базы данных. Если на данном этапе вы столкнетесь с какими либо проблемами, то можете обратиться к команде «activerecord-clean-db-structure».
5. Отслеживание транзакций и отмена блокировок
Язык Rails любит помещать различную информацию в транзакции, особенно в своих многоуровневых моделях [1]. Но следует контролировать одно действие, которое учитывается в транзакциях и, которое может создавать проблемы при масштабировании БД (листинг 6).
Листинг 6 – Обзор транзакции
Первый оператор функции «UPDATE» будет удерживать блокировку строки «organizations» с id «123», с самого начала и до функции «COMMIT».
Для «обхода» этой ситуации можно представить другой запрос к той же самой «organizations», который, например, выполняет ту же транзакцию, но уже другим пользователем. Как правило, при переходе к такому запроса придется ожидать больше, так как в первую очередь будет выполняться до первого «COMMIT`а» основного пользователя. Но разработчик может это исправить, упорядочив транзакцию так, чтобы UPDATE» выполнялся ближе к концу и обработал за раз больше полей.
Чтобы заранее обнаружить и устранить проблемы такого типа, можно установить дополнительную функцию в PostgreSQL: «log_lock_eaits = on».
6. Контроль подключения к базе данных
Язык Rails по умолчанию хранит в себе множество пулов подключений к базе данных. Когда необходимо выполнить новый запрос, он берет одно из соединений текущего пула и передает его управляющему приложению. По мере увеличения масштабов базы данных в Rails приложение может содержать в себе более сотни таких подключений, хотя только часть из них будет работать. Решением этой проблемы является использование «менеджера соединений», например «pgBuncer`а» [2]. Менеджер соединений будет открывать их только тогда, когда для БД будет это необходимо. Так же, его функцией является блокировка всех неактивных соединений, которые не выполняют никакой работы.