PL/pgSQL
Отладка
12
Авторские права
© Postgres Professional, 2017–2020
Авторы: Егор Рогов, Павел Лузанов
Использование материалов курса
Некоммерческое использование материалов курса (презентации,
демонстрации) разрешается без ограничений. Коммерческое
использование возможно только с письменного разрешения компании
Postgres Professional. Запрещается внесение изменений в материалы
курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу:
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за
любые повреждения и убытки, включая потерю дохода, нанесенные
прямым или непрямым, специальным или случайным использованием
материалов курса. Компания Postgres Professional не предоставляет
каких-либо гарантий на материалы курса. Материалы курса
предоставляются на основе принципа «как есть» и компания Postgres
Professional не обязана предоставлять сопровождение, поддержку,
обновления, расширения и изменения.
2
Темы
Проверки корректности
Отладчик PL/pgSQL
Служебные сообщения и различные способы их реализации
Трассировка сеансов
3
Проверки корректности
Проверки времени компиляции и времени выполнения
plpgsql.extra_warnings
plpgsql.extra_errors
дополнительные проверки в расширении plpgsql_check
Проверки в коде
команда ASSERT
Тестирование
Отладка предполагает выполнение программы и изучение
возникающих проблем, обычно с помощью специализированного
отладчика или с помощью вывода отладочных сообщений.
Но можно заранее исключить определенные классы ошибок, включив
проверку исходного кода во время компиляции и выполнения. Это
управляется параметрами plpgsql.extra_warnings и plpgsql.extra_errors,
как рассматривалось в теме «PL/pgSQL. Выполнение запросов».
Там же рассматривалось применение расширения plpgsql_check,
которое обеспечивает более широкий спектр проверок.
Еще одна возможность обезопасить свой код — добавить в него
проверки условий, которые всегда должны выполняться (т. н. «sanity
check»). Удобный способ для этого — SQL-команда ASSERT.
Нельзя не сказать и о важности тестирования кода. Тестирование не
только позволяет изначально убедиться, что код работает так, как
задумано, но и облегчает его дальнейшую модификацию — дает
уверенность в том, что изменения не поломали существующий
функционал. Мы не будем затрагивать эту тему; отметим только, что
тестирование кода, работающего с базой данных, может оказаться
непростым делом из-за необходимости подготовки тестовых примеров.
5
PL/pgSQL Debugger
Состав
расширение pldbgapi
встроенная поддержка в некоторых графических средах
Возможности
установка точек прерывания
пошаговое выполнение
проверка и установка значений переменных
не требуется изменение кода
отладка работающих приложений
PL/pgSQL Debugger — это отладчик для PL/pgSQL. Представляет
собой расширение pldbgapi, которое официально поддерживается
разработчиками PostgreSQL.
Расширение pldbgapi — это набор интерфейсных функций для сервера
PostgreSQL, которые позволяют устанавливать точки прерывания,
пошагово выполнять код программ, проверять и устанавливать
значений переменных.
Исходный код отлаживаемых программ изменять не требуется, что
дает возможность выполнять отладку работающих приложений. Т. е.
процесс отладки не обязательно запускать отдельно, можно
подключиться к уже работающему сеансу и начать его отладку.
Непосредственно пользоваться этими функциями неудобно, они
в первую очередь предназначены для графических сред разработки.
Некоторые из таких сред (включая pgAdmin) имеют встроенный
интерфейс для отладки. Но чтобы им воспользоваться, сначала все
равно придется установить расширение pldbgapi в соответствующую
базу данных.
Исходный код отладчика доступен по ссылке:
6
Служебные сообщения
Не только отладка кода
мониторинг долго выполняющихся процессов
ведение журнала приложения
Подходы к реализации
вывод на консоль или в журнал сервера
запись в таблицу или в файл
передача информации другим процессам
Второй способ отладки предполагает добавление в важные места кода
служебных сообщений, содержащих текущий контекст. Анализируя
сообщения можно понять, что именно пошло не так.
Помимо собственно отладки, служебные сообщения могут выполнять
и другие функции. Сообщения помогут определить, на каком этапе
выполнения находится долго выполняющийся процесс. По аналогии
с журналом сообщений СУБД приложение может записывать в свой
собственный журнал важную информацию. Например, данные
о запуске отчетов: название отчета, пользователь, когда, с какими
параметрами и т. д. Такая информация может сильно облегчить работу
специалистов поддержки.
Можно выделить несколько подходов к реализации служебных
сообщений в PL/pgSQL. Помимо уже знакомой команды RAISE,
позволяющей выводить сообщения на консоль (а также в журнал
сообщений сервера), можно отправлять сообщения другому процессу,
записывать сообщения в таблицу или в файл.
При выборе того или иного подхода нужно обращать внимание на
много вопросов. Являются ли сообщения транзакционными
тправляются не дожидаясь окончания транзакции или только при ее
завершении)? Можно ли одновременно использовать в нескольких
сеансах? Как организовать доступ к журналу сообщений и как очищать
его от старых записей? Какое влияние оказывают журналирование на
на производительность? Требуется ли модификация исходного кода?
7
Команда RAISE
DEBUG
LOG
NOTICE
INFO
WARNING
RAISE
DEBUG INFO NOTICE WARNING ERROR LOG FATAL PANIC
log_min_messages
Журнал сервера
DEBUG LOG NOTICE WARNING ERROR FATAL PANIC
client_min_messages
Клиент
Мы уже встречались с командой RAISE. Она служит и для вызова
исключительных ситуаций, что подробно рассматривалось в теме «PL/
pgSQL. Обработка ошибок», и для отправки сообщений. Причем
сообщения можно не только отправлять клиенту, но и записывать
в журнал сервера.
В простом случае для отладки нужно добавить вызовы RAISE NOTICE
в код функции, запустить функцию на выполнение (например в сеансе
psql) и проанализировать получаемые по ходу выполнения сообщения.
Сообщения RAISE нетранзакционные: они отправляются асинхронно и
не зависят от статуса завершения транзакции.
Для управления отправкой сообщений используются уровень
сообщения (DEBUG, LOG, NOTICE, INFO, WARNING) и параметры
сервера. Он значений параметров зависит, будет ли сообщение
отправлено клиенту (client_min_messages) и/или записано в журнал
сервера (log_min_messages). Сообщение будет отправлено, если
уровень команды RAISE равен значению соответствующего параметра
или больше его (находится правее на рисунке).
Значения параметров по умолчанию настроены так, что сообщения
с уровнем NOTICE отправляются только клиенту, с уровнем LOG —
только в журнал, а с уровнем WARNING — и клиенту, и в журнал.
Сообщения с уровнем INFO всегда отправляются клиенту, их нельзя
перехватить параметром client_min_messages.
9
Процесс→процесс (IPC)
NOTIFY → LISTEN
команды SQL
транзакционное выполнение, неудобно для отладки
Статус сеанса
параметр application_name
виден в представлении pg_stat_activity и выводе команды ps
можно использовать в журнальных сообщениях
Серверные процессы в PostgreSQL могут обмениваться информацией
между собой.
Среди встроенных решений можно отметить следующие.
Использование команд NOTIFY для отправки сообщений в одном
процессе и LISTEN для получения в другом. Но эти команды
являются транзакционными, поэтому они неудобны для отладки:
1. Сообщения отправляются только при фиксации транзакции, а не
сразу после выполнения NOTIFY. Поэтому невозможно следить за
ходом процесса.
2. Если транзакция завершится неуспешно, то сообщения вообще не
будут отправлены.
Использование параметра application_name.
Сеанс с долго выполняющимся процессом может периодически
записывать статус выполнения в application_name. В другом сеансе
администратор может опрашивать представление pg_stat_activity,
содержащем подробную информацию о всех выполняющихся
сеансах. Также значение application_name обычно видно в выводе
команды ps.
Значение application_name также можно записывать в журнал
сервера (настраивая параметр log_line_prefix). Это облегчит поиск
нужных строк в журнале.
11
Процесс→таблица
Расширение dblink
входит в состав сервера
накладные расходы на создание соединения
Автономные транзакции
коммерческий дистрибутив (Postgres Pro Enterprise)
Еще один способ сохранения отладочных сообщений — запись
в таблицу базы данных.
К плюсам данного подхода относится то, что параллельная работа
и доступ журналу обеспечиваются средствами самой СУБД.
Однако нужно позаботиться о том, чтобы вставка в таблицу была
нетранзакционной. Для этого можно использовать расширение dblink,
идущее в составе сервера PostgreSQL. Это расширение позволяет
открыть новое соединение к той же самой базе данных, поэтому
вставка в таблицу выполняется в другой — независимой — транзакции.
К минусам данного подхода относится то, что открытие нового
соединения требует дополнительных ресурсов сервера.
Подробнее работа с dblink рассматривается в курсе DEV2.
В коммерческих дистрибутивах, например Postgres Pro Enterprise,
доступен механизм автономных транзакций, не имеющий таких
существенных накладных расходов, которые характерны для dblink.
13
Процесс→файл
Расширение adminpack
входит в состав сервера
в том числе позволяет записывать текстовые файлы
Недоверенные языки
например, PL/Perl
Вести запись сообщений можно и в файл операционной системы.
Для этого, например, можно использовать расширение adminpack,
которое позволяет записывать данные в любой файл, доступ
к которому есть у пользователя ОС postgres.
Другой вариант — написать функцию на недоверенном языке (таком,
как PL/Perl — plperlu), которая будет выполнять ту же задачу.
Различные языки серверного программирования рассматриваются
в курсе DEV2.
15
Трассировка SQL
Стандартная трассировка в журнал сообщений
накладные расходы на запись в журнал
большой размер файла журнала
требуются инструменты для анализа
нужен доступ к журналу (безопасность)
Настройки
долго выполняющиеся команды log_min_duration_statement
какие команды записывать log_statement
контекст сообщения log_line_prefix
В некоторых случаях может оказаться полезной трассировка всего
происходящего в коде. Штатными средствами можно получить
в журнале сообщений сервера SQL-запросы сеансов. Надо учитывать:
Высоконагруженное приложение может выполнять огромное число
запросов. Их запись в файл журнала может оказывать влияние на
производительность подсистемы ввода/вывода.
В большинстве случаев требуются специальные инструменты для
анализа такого объема данных. Стандарт де-факто — pgBadger.
К файлу журнала на сервере может не быть доступа у разработчи-
ков приложений. К тому же в журнале промышленной системе могут
оказаться команды, содержащие конфиденциальную информацию.
Для настройки трассировки имеется ряд параметров, основные из
которых приведены на слайде. Полный список:
Не обязательно устанавливать конфигурационные параметры для
всего кластера. Их действие можно ограничить отдельными сеансами
при помощи команд SET, ALTER DATABASE, ALTER ROLE ак
рассказы-валось в темах «Обзор базового инструментария. Установка
и управление, psql» и «Организация данных. Логическая структура»).
16
Трассировка SQL-команд
Расширение auto_explain
запись в журнал планов выполнения запросов
трассировка вложенных запросов
Настройки
планы долгих команд auto_explain.log_min_duration
вложенные запросы auto_explain.log_nested_statements
При включении трассировки SQL-команды попадают в журнал в том
виде, в каком они отправлены на сервер. Если была вызвана
подпрограмма PL/pgSQL, то в журнале будет записан только вызов
этой подпрограммы (например, оператор SELECT или CALL), но не
будет тех команд, которые выполняются внутри подпрограммы.
Чтобы увидеть в журнале запросы не только верхнего уровня, но и
вложенные, потребуется штатное расширение auto_explain.
Как следует из названия расширения, его основная задача —
записывать в журнал не только текст команды, но и план ее
выполнения. Это тоже может оказаться полезно, хотя относится не
к трассировке как таковой, а к оптимизации запросов (которая
рассматривается в курсе QPT).
17
Трассировка PL/pgSQL
Расширение plpgsql_check
накладные расходы на запись сообщений
большой объем выдачи
Основные настройки
включение трассировки plpgsql_check.enable_tracer
plpgsql_check.tracer
уровень сообщений plpgsql_check.tracer_errlevel
Чтобы разобраться по журналу, какой процедурный код выполнялся,
придется сопоставить SQL-запросы с подпрограммами на PL/pgSQL,
а это может оказаться не просто. Стандартной возможности для
трассировки PL/pgSQL-кода не предусмотрено, но расширение Павла
Стехуле plpgsql_checkоторое упоминалось в теме «PL/pgSQL.
Выполнение запросов») позволяет ее выполнить.
Подобная трассировка вызывает большие накладные расходы и
должна использоваться только для отладки, но не в промышленной
эксплуатации.