Когда pg_stat_activity обрезает текст запроса
Как диагностировать длинный динамический SQL через временное логирование для отдельной роли, если pg_stat_activity уже обрезал текст.
PostgreSQLМониторингБезопасность данныхЗвонок раздался внезапно.
— Макс, привет! У нас проблема, — быстро заговорил Сергей. — Висит долгий запрос, а 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, а админы помогали увидеть их в полный рост. Идеальный баланс во вселенной.