Уровни логирования в PostgreSQL, MySQL и MongoDB: настройка и практическое применение | AdminWiki

Уровни логирования в PostgreSQL, MySQL и MongoDB: настройка и практическое применение

01 октября 2026 13 мин. чтения

Зачем управлять уровнями логирования в СУБД

Уровень логирования работает как фильтр: всё, что ниже выставленного порога, в файл не попадает. В PostgreSQL этим порогом управляет log_min_messages, в MySQL - log_error_verbosity, в MongoDB - systemLog.verbosity с уточнением по компонентам. Одно значение в конфиге решает, найдёте вы причину инцидента за минуту или будете собирать картину по косвенным признакам.

Практических задач, которые закрывает настройка уровней, три. Отладка медленных запросов требует длительностей и планов выполнения. Аудит доступа отвечает на вопросы, кто подключился, откуда и какие объекты менял. Мониторинг ошибок даёт поток событий для алертов: WARNING, ERROR, FATAL, PANIC.

Цена ошибки высока в обе стороны. log_statement = 'all' на базе с пятью тысячами транзакций в секунду пишет десятки гигабайт в сутки, и диск заканчивается быстрее, чем вы вспомните про ротацию. Обратный случай незаметнее: при log_min_messages = fatal предупреждения о нехватке места и ошибки транзакций в лог не пишутся, а первый сигнал о проблеме приходит от пользователей.

Сравним три движка по шкалам и основным параметрам.

СУБДУровниОсновной параметрПо умолчаниюКуда пишет
PostgreSQLDEBUG5 - DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, PANIClog_min_messageswarningstderr, файл, syslog, csvlog
MySQLERROR, WARNING, NOTElog_error_verbosity2error log, slow log, general log
MongoDBverbosity 0 - 5 по компонентамsystemLog.verbosity, systemLog.component.*.verbosity0файл или syslog

Матрица выбора под задачу выглядит так.

ЗадачаPostgreSQLMySQLMongoDB
Медленные запросыlog_min_duration_statement = 1000slow_query_log = 1, long_query_time = 1operationProfiling.mode: slowOp, slowOpThresholdMs: 100
Аудит доступаlog_connections, log_disconnections, log_statement = 'ddl'audit_log (Enterprise), server_audit (MariaDB)auditLog (Enterprise)
Мониторинг ошибокlog_min_messages = warning, log_min_error_statement = errorlog_error_verbosity = 2systemLog.verbosity: 0, systemLog.component.accessControl.verbosity: 1

Какие события вообще стоит писать, а какие создают шум и риски для безопасности, разбираем в отдельном материале про критерии эффективного логирования.

Уровни логирования в PostgreSQL: от DEBUG до PANIC

В PostgreSQL все сообщения выстроены в одну шкалу серьёзности. log_min_messages задаёт минимальный уровень, который попадёт в серверный лог, и по умолчанию равен warning, поэтому INFO и NOTICE в файл не пишутся. Это значение зафиксировано в официальной документации PostgreSQL в разделе Error Reporting and Logging.

  • DEBUG1 - DEBUG5: внутренние детали работы. debug1 показывает планы и ключевые шаги исполнения, debug5 добавляет разбор блокировок и работу с буферами. Объём логов растёт в разы на каждом шаге.
  • INFO: сообщения, запрошенные пользователем, например вывод VACUUM VERBOSE. Всегда уходят клиенту.
  • NOTICE: уведомления о полезных событиях, например об усечении длинного идентификатора до 63 символов.
  • WARNING: оператор выполняется, но ситуация требует внимания.
  • ERROR: ошибка оператора, текущая транзакция прерывается.
  • LOG: сообщения для администратора: контрольные точки, autovacuum, переключение WAL. В шкале серьёзности LOG стоит между ERROR и FATAL.
  • FATAL: сессия завершается, например при неверном пароле или исчерпании соединений.
  • PANIC: сбой всего кластера, все сессии обрываются, база уходит в recovery.

Пороги доставки клиенту и в файл различаются. За лог отвечает log_min_messages, за сообщения клиенту - client_min_messages. Текст оператора, который привёл к ошибке, добавляется по порогу log_min_error_statement: значение warning означает, что в лог попадёт и SQL, вызвавший предупреждение.

Как выбрать уровень для отладки, аудита и мониторинга

Для отладки конкретной проблемы включайте debug1 и не глубже. debug4 и debug5 имеет смысл держать минутами и на тестовом стенде, потому что на нагруженной базе они добавляют сотни мегабайт в час и заметно нагружают диск. Если нужны планы выполнения медленных запросов, включите расширение auto_explain и параметр auto_explain.log_min_duration: тогда планы попадут в лог только для запросов дольше порога.

Для аудита доступа достаточно log_connections и log_disconnections, которые фиксируют факт подключения, пользователя, базу и адрес клиента. Тексты операторов добавляет log_statement: значение ddl пишет только изменения схемы, mod - ещё и INSERT, UPDATE, DELETE, all - всё подряд. Значение all оправдано на время разбора инцидента, не как постоянная конфигурация.

Для мониторинга ошибок рабочий набор: log_min_messages = warning и log_min_error_statement = error. В лог попадут предупреждения, ошибки, фатальные события и паники, то есть всё, на что стоит вешать алерты. Схему доступа к самой базе проверьте по чек-листу аудита PostgreSQL, MySQL и MongoDB.

Пример настройки log_min_messages и slow_query_log

Отдельного параметра slow_query_log в PostgreSQL нет, его роль выполняет log_min_duration_statement. Значение указывается в миллисекундах: 1000 означает запись всех операторов, которые выполнялись секунду и дольше, -1 отключает логирование, 0 пишет вообще всё.

# Уровни сообщений в серверный лог
log_min_messages = warning
log_min_error_statement = error

# Логирование медленных запросов: 1000 мс = 1 секунда
log_min_duration_statement = 1000

# Аудит подключений
log_connections = on
log_disconnections = on
log_statement = 'ddl'

# Формат строки: время, PID процесса, пользователь@база
log_line_prefix = '%m [%p] %q%u@%d '

# Файлы и встроенная ротация
log_destination = 'stderr'
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_truncate_on_rotation = on

Разберём ключевые строки. log_min_messages = warning оставляет в логе предупреждения и выше. log_min_error_statement = error добавляет текст оператора, который завершился ошибкой. log_min_duration_statement = 1000 даёт основу для анализа производительности. log_line_prefix с %m, %p, %q, %u и %d нужен, чтобы по строке можно было восстановить время, процесс, пользователя и базу; символ %q обрывает шаблон для фоновых процессов, у которых нет пользователя и базы. log_rotation_age и log_rotation_size включают встроенную ротацию, а log_truncate_on_rotation не даёт именам файлов накапливать старые данные.

Применение настроек без перезапуска и проверка результата:

SELECT pg_reload_conf();

SHOW log_min_messages;
SHOW log_min_duration_statement;

SELECT name, setting, unit
FROM pg_settings
WHERE name IN ('log_min_messages', 'log_min_duration_statement', 'log_statement', 'log_connections');

pg_reload_conf() перечитывает postgresql.conf на живой базе, рестарт для этих параметров не требуется. Значение log_min_messages = debug1 на нагруженной системе перечитайте дважды: объём логов вырастет на порядок, а вместе с ним и нагрузка на диск.

Уровни логирования в MySQL: ERROR, WARNING, NOTE

В MySQL уровней всего три, и управляет ими log_error_verbosity. Значение 1 пишет только ошибки, 2 добавляет предупреждения и применяется по умолчанию, 3 включает заметки NOTE и подробности о работе сервера. Значение по умолчанию 2 подтверждено официальной документацией MySQL Server. Параметр динамический, поэтому SET GLOBAL log_error_verbosity = 3 действует без рестарта.

Уровни привязаны к типу журнала. Slow query log и general query log собственной шкалы не имеют: они либо включены целиком, либо выключены.

ЖурналПараметрыЧто записываетКогда включать
Error loglog_error, log_error_verbosityОшибки запуска, InnoDB, репликацииПостоянно
Slow query logslow_query_log, long_query_timeЗапросы дольше порогаПостоянно в продакшене
General query loggeneral_log, log_outputКаждый оператор от клиентаТолько на время отладки
Audit logaudit_log (Enterprise), server_audit (MariaDB)Подключения, DDL, доступ к таблицамКогда нужен аудит
Binary loglog_binИзменения данных для репликацииРепликация и восстановление

Настройка slow_query_log и long_query_time

[mysqld]
log_error = /var/log/mysql/error.log
log_error_verbosity = 2

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
log_throttle_queries_not_using_indexes = 60

# general log держим выключенным
general_log = 0
general_log_file = /var/log/mysql/general.log

long_query_time по умолчанию равен 10 секундам, минимальное значение - 0; значение 1 секунда даёт заметно больше полезных данных. Оба значения зафиксированы в документации MySQL по slow query log. log_queries_not_using_indexes = 1 добавляет в slow log запросы без индексов, и именно этот параметр чаще всего забивает диск: на плохо оптимизированной схеме он превращает slow log в general log. throttling через log_throttle_queries_not_using_indexes ограничивает запись одинаковых запросов, например одной строкой в 60 секунд.

Включить и проверить на живой базе:

SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
SET SESSION long_query_time = 0.1;

SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
SHOW GLOBAL STATUS LIKE 'Slow_queries';

Анализ slow log без ручного чтения файла:

mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

pt-query-digest /var/log/mysql/slow.log > /tmp/slow-report.txt

mysqldumpslow сортирует запросы по суммарному времени, pt-query-digest строит профиль нагрузки с распределением по запросам и таблицам. Порог slow_query_log имеет смысл пересматривать вместе с ростом нагрузки, а общие подходы к настройке под пиковые значения собраны в материале про производительность PostgreSQL и MySQL под нагрузкой.

Аудит доступа через general_log и audit_log

general_log пишет каждый оператор от каждого клиента. Включается одной командой на время отладки:

SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 'ON';

SELECT event_time, user_host, argument
FROM mysql.general_log
ORDER BY event_time DESC
LIMIT 20;

Вывод в таблицу удобен для выборок, вывод в файл дешевле по нагрузке. В обоих случаях логи содержат литералы запросов с персональными данными, поэтому доступ к ним ограничивают и выключают сбор сразу после разбора: SET GLOBAL general_log = 'OFF'. На боевой базе general_log добавляет заметный оверхед на каждый запрос.

Для постоянного аудита используйте плагин audit_log в MySQL Enterprise или MariaDB Audit Plugin в сборках MariaDB. Плагин умеет писать только нужные события: подключения, изменения схемы, доступ к конкретным таблицам. Проверить, не осталось ли лишних прав у учётных записей, помогает руководство по аудиту безопасности баз данных.

Логирование в MongoDB: уровни и параметры

В MongoDB нет одной шкалы на весь сервер. Вместо неё используется verbosity от 0 до 5 для каждого компонента: query, command, accessControl, storage, network, replication, index, write. Уровень 0 даёт обычные информационные сообщения, 1 и выше включают отладочный вывод с растущей детализацией. systemLog.verbosity задаёт общий уровень, а блок component переопределяет его точечно. Полный список параметров приведён в справочнике конфигурационных опций MongoDB.

Настройка verbosity и profiling в mongod.conf

systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
  verbosity: 0
  component:
    query:
      verbosity: 1
    accessControl:
      verbosity: 1

operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100

verbosity выше 2 резко увеличивает объём файла: на активной базе debug-вывод по компоненту query измеряется гигабайтами в сутки. Значение 1 по конкретному компоненту даёт компромисс, который можно держать включённым постоянно. destination: file пишет в path, вариант syslog отправляет события в системный журнал.

Профилировка отвечает за медленные операции и пишет результат не в файл лога, а в системную коллекцию system.profile. slowOpThresholdMs задаёт порог в миллисекундах; в приведённом примере конфигурации используется значение 100. Официальное значение по умолчанию для этого параметра в переданных материалах не подтверждено, поэтому перед изменением сверьтесь с документацией вашей версии MongoDB. Управление на живой базе:

db.setLogLevel(1, "query");
db.adminCommand({ setParameter: 1, logComponentVerbosity: { query: { verbosity: 1 } } });

db.setProfilingLevel(1, { slowms: 100 });
db.getProfilingStatus();

db.system.profile.find({ millis: { $gt: 100 } }).sort({ ts: -1 }).limit(10);

В конфиге порог называется slowOpThresholdMs, в командах setProfilingLevel исторически используется slowms: оба имени задают одно и то же. Режим all профилирует каждую операцию и подходит только для короткой диагностики. Файл лога удобно разбирать утилитой mloginfo из набора mtools:

mloginfo --queries /var/log/mongodb/mongod.log
mloginfo --connections /var/log/mongodb/mongod.log

Типичные ошибки конфигурации mongod и способы их обойти разобраны в гайде про MongoDB в продакшене.

Аудит доступа в MongoDB

auditLog доступен только в MongoDB Enterprise. В Community Edition этого механизма нет, поэтому аудит доступа закрывают логированием компонента accessControl и метриками подключений. Пример блока для Enterprise:

security:
  authorization: enabled

auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/audit.log
  filter: '{ atype: { $in: [ "authenticate", "authCheck" ] } }'

Фильтр оставляет только события аутентификации и проверки прав, иначе файл аудита растёт со скоростью лога запросов. Формат JSON упрощает разбор внешними системами: строки можно отдавать в Elasticsearch или Loki без дополнительного парсинга. Включение аудита добавляет нагрузку на диск, поэтому сначала оцените поток событий на стенде.

В Community Edition контроль доступа строится на ролевой модели и мониторинге числа соединений:

db.serverStatus().connections;
db.adminCommand({ logRotate: 1 });

Сбор, ротация и анализ логов СУБД

Ротация - обязательный элемент конфигурации, а не опция. Логи без ограничения по размеру съедают диск, а вместе с ним и саму базу. Работают три подхода: встроенная ротация средствами СУБД, logrotate и централизованный сбор через syslog или journald. Выбирайте один основной и не смешивайте: встроенная ротация PostgreSQL вместе с внешним logrotate без copytruncate даёт пустые файлы и потерянные записи.

Настройка logrotate для PostgreSQL, MySQL и MongoDB

/var/log/postgresql/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 640 postgres postgres
    sharedscripts
    postrotate
        /usr/bin/pg_ctlcluster 16 main reload > /dev/null 2>&1
    endscript
}
/var/log/mysql/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 640 mysql adm
    postrotate
        test -x /usr/bin/mysqladmin && mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs
    endscript
}
/var/log/mongodb/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 640 mongodb mongodb
    postrotate
        /bin/kill -SIGUSR1 $(cat /var/run/mongodb/mongod.pid 2>/dev/null) 2>/dev/null
    endscript
}

Параметры означают следующее. daily задаёт суточный интервал, rotate 14 хранит две недели истории, compress сжимает старые файлы, delaycompress откладывает сжатие на цикл, чтобы процесс не писал в только что закрытый файл. missingok и notifempty защищают от ошибок при отсутствии файлов. create 640 с указанием владельца и группы обязателен: после ротации новый файл получит права демона, иначе СУБД не сможет в него писать.

По умолчанию MongoDB использует поведение --logRotate rename: mongod или mongos переименовывает текущий лог-файл, добавляя к имени метку времени UTC, открывает новый лог-файл, закрывает старый и направляет все новые записи в новый файл. Это подтверждено официальной документацией MongoDB. Вариант reopen, при котором процесс переоткрывает тот же файл по сигналу SIGUSR1, в переданных материалах не подтверждён, поэтому при использовании SIGUSR1 в postrotate обязательно сверьтесь с документацией вашей версии и проверьте фактическое поведение на стенде. Аналогично: перечитывание конфигурации PostgreSQL по SIGHUP и переоткрытие логов MySQL через mysqladmin flush-logs в переданных материалах не подтверждены, хотя эти механизмы широко используются на практике.

Для централизованного сбора подойдут rsyslog или journald. В journald.conf ограничьте SystemMaxUse, иначе журнал вытеснит данные приложения. MongoDB умеет писать напрямую в syslog, а PostgreSQL требует смены log_destination на syslog и стиль префикса syslog. Ограничение: journald хранит записи в двоичном формате, и разбор внешними утилитами без экспорта невозможен.

Инструменты анализа логов: pgBadger, pt-query-digest, mtools

pgBadger собирает HTML-отчёт по логам PostgreSQL: топ запросов, время отклика, ошибки, подключения. Утилита разбирает только логи с подходящим log_line_prefix, потому что идентифицирует записи по времени, PID, пользователю, базе и адресу клиента.

pgbadger /var/log/postgresql/postgresql-16-main.log -o /var/www/reports/pg-report.html

pt-query-digest анализирует slow log MySQL и Percona Server, группируя запросы по подписи и показывая суммарное время, число вызовов и долю от общей нагрузки:

pt-query-digest --limit 20 /var/log/mysql/slow.log

mtools закрывает MongoDB: mloginfo собирает статистику по запросам и подключениям, mlogfilter отбирает нужные записи по времени и компоненту. Запускайте разбор по расписанию или после релиза, а не разово при инциденте.

Практические рекомендации и чек-лист

  1. В продакшене держите log_min_messages = warning, log_error_verbosity = 2, systemLog.verbosity: 0. Уровни DEBUG и verbosity выше 2 включайте точечно и на ограниченное время.
  2. Логируйте медленные запросы с явным порогом: log_min_duration_statement = 1000, long_query_time = 1, slowOpThresholdMs = 100. Начните с порога выше и снижайте по мере появления свободного места.
  3. Для аудита доступа используйте log_connections и log_disconnections с log_statement = 'ddl' в PostgreSQL, audit_log или server_audit в MySQL, auditLog в MongoDB Enterprise. general_log и log_statement = 'all' оставляйте только на период разбора.
  4. Настройте ротацию одним способом: logrotate с daily, rotate 14 и compress либо встроенные параметры log_rotation_age и log_rotation_size. Для MongoDB учитывайте, что по умолчанию используется поведение rename, а вариант reopen требует проверки на вашей версии.
  5. Ограничьте доступ к файлам логов правами 640 и отдельной группой. В строках встречаются литералы запросов, адреса клиентов и имена учётных записей.
  6. Повесьте алерты на размер каталога с логами, на события уровня FATAL и PANIC, а также на рост числа подключений через db.serverStatus().connections.
  7. Проверяйте конфигурацию перед применением: SELECT pg_reload_conf() в PostgreSQL действует без рестарта, в MySQL часть параметров динамические, а verbosity MongoDB меняется через db.setLogLevel без перезапуска.

Чек-лист перед тем, как считать настройку логирования завершённой:

  • Уровни соответствуют задаче: DEBUG и verbosity выше 2 выключены в продакшене.
  • Порог медленных запросов задан явно и записан в конфиге, а не выставлен вручную в сессии.
  • Ротация настроена, старые файлы сжимаются, глубина хранения не меньше 7-14 дней.
  • general_log выключен, log_queries_not_using_indexes ограничен по частоте или отключён.
  • Доступ к каталогу логов ограничен, у файлов права 640 и корректный владелец.
  • Алерты на размер логов и на критичные уровни настроены и проверены тестовым событием.
  • Инструмент анализа (pgBadger, pt-query-digest, mtools) запускается по расписанию.
  • Изменения конфигурации применены без рестарта там, где это возможно, и проверены командой SHOW или SELECT из pg_settings.

Начните с одной базы: выставьте порог медленных запросов, включите ротацию и посмотрите через неделю, сколько данных собралось. Дальше добавьте аудит доступа и алерты, опираясь на реальный объём логов, а не на предположения.

Поделиться: