Материалы / Истории / Когда pg_stat_activity обрезает текст запроса
История

Когда pg_stat_activity обрезает текст запроса

Как диагностировать длинный динамический SQL через временное логирование для отдельной роли, если pg_stat_activity уже обрезал текст.

Звонок раздался внезапно.

— Макс, привет! У нас проблема, — быстро заговорил Сергей. — Висит долгий запрос, а pg_stat_activity показывает только начало. Вытащить из кода его не можем, его JPA на лету генерирует. Можешь по-быстрому поднять track_activity_query_size?

Макс сделал глоток остывшего кофе.

— Могу. Только для этого нужно будет перезагрузить прод. Готовы на полчаса всё остановить?

В трубке повисла тяжёлая пауза.

— Понял, — вздохнул Сергей. — Не вариант. И что делать?

— Есть один способ, — ответил Макс, — но он не покажет то, что уже висит в воздухе.

— В смысле? — не понял Сергей. — Он покажет текущий запрос?

— Нет. Текущий — нет. В этой базе pg_stat_statements выключен, как и auto_explain. Мы не можем без танцев с бубном заставить Postgre раскрыть текст уже выполняющегося запроса, если он оказался длиннее, чем track_activity_query_size. Но вот следующий запрос — да, он попадёт в логи целиком. Сможешь запустить нужное действие в вашей программе, когда я скажу?

Сергей задумался на секунду.

— Да. А как ты это сделаешь?

— Очень просто, — Макс расшарил экран. — Включу подробное логирование, но только для одного пользователя. Команда такая:

ALTER ROLE a_very_busy_user SET log_statement = 'all';

— То есть всё, что он выполнит дальше, улетит в логи? — уточнил Сергей.

— Да, для новых сессий этой роли и без перезапуска базы. Но сначала ограничим диагностическое окно и проверим, не выполняет ли та же роль чувствительные или очень частые запросы: log_statement = 'all' способен записать в журнал SQL с персональными данными и секретами в литералах, быстро увеличить объём логов и нагрузку. Лучше использовать отдельную диагностическую роль или максимально узкий контур.

— Настройка роли не меняет уже открытые соединения. Поэтому контролируемо пересоздадим только нужный пул на одном экземпляре приложения, убедившись, что это не оборвёт пользовательские транзакции.

— Понял, а я запущу нужное действие на этом сервере? — подтвердил Сергей.

Через пять минут полный текст проблемного запроса был в защищённом канале диагностики. Проблема сдвинулась с мёртвой точки.

— Теперь главное не забыть выключить логирование. — напомнил Макс.

ALTER ROLE a_very_busy_user RESET log_statement;

Сергей недоверчиво хмыкнул:

— А зачем выключать? Вроде же полезная штука.

— Полезная, но очень шумная и чувствительная. RESET вернёт роли значение из конфигурации базы или сервера, а не навяжет ей none. После диагностики ещё нужно проверить ротацию и доступ к логам.

Так и работали. Разработчики генерировали проблемы с помощью JPA, а админы помогали увидеть их в полный рост. Идеальный баланс во вселенной.