15%

Сэкономьте 15% на всех хостинговых услугах

Проверьте свои навыки и получите скидку на любой тарифный план

Используйте код:

Skills
Начать
14.10.2024

Как включить журнал медленных запросов в MySQL и MariaDB

Журнал медленных запросов — это встроенная диагностическая функция MySQL и MariaDB, которая записывает каждый SQL-оператор, время выполнения которого превышает настраиваемый порог. Он фиксирует продолжительность выполнения запроса, время блокировки, количество проверенных строк, количество отправленных строк и полный текст SQL — предоставляя администраторам баз данных и разработчикам точный файловый журнал аудита каждого запроса, снижающего производительность приложения.

Его включение — одно из наиболее эффективных действий при настройке производительности базы данных. В отличие от универсальных инструментов мониторинга, журнал медленных запросов точно определяет операторы, ответственные за задержки, что делает его незаменимым для оптимизации индексов, реструктуризации запросов и планирования ресурсов на любом сервере — от однопользовательской среды VPS Hosting до многоузлового выделенного кластера баз данных.

Почему журнал медленных запросов важнее базового мониторинга

Большинство команд обращаются к EXPLAIN или SHOW PROCESSLIST реактивно, после того как пользователи сообщают о замедлении работы. Журнал медленных запросов работает проактивно: он накапливает данные за часы или дни реального трафика, фиксируя периодически возникающие проблемы, которые никогда не появляются в окне ручной проверки.

Ключевые операционные преимущества включают:

  • Изоляция узких мест — позволяет отличить полное сканирование таблиц, ограниченное CPU, от проблем конкуренции блокировок с помощью соотношений Query_time и Lock_time
  • Анализ пробелов в индексах — флаг log_queries_not_using_indexes выявляет каждый запрос, выполняющий полное сканирование, независимо от его фактического времени выполнения
  • Обнаружение регрессий — сравнение снимков журнала до и после развёртывания показывает, привёл ли новый код к появлению более медленных шаблонов запросов
  • Доказательная база для планирования ресурсов — значения Rows_examined, на порядки превышающие Rows_sent, указывают на отсутствующие или неправильно используемые индексы, которые усугубляются под нагрузкой

MySQL и MariaDB: сравнение функций журнала медленных запросов

Оба движка используют одну и ту же базовую инфраструктуру журнала медленных запросов, унаследованную от MySQL 5.1, однако MariaDB расширила её несколькими существенными способами.

ФункцияMySQL 8.0+MariaDB 10.6+
Базовое ведение журнала медленных запросовДаДа
Гранулярность `long_query_time`МикросекундыМикросекунды
`log_queries_not_using_indexes`ДаДа
`log_slow_admin_statements`ДаДа
`log_slow_slave_statements`ДаДа (также реплика)
`min_examined_row_limit`ДаДа
`log_slow_verbosity` (расширенная статистика)НетДа (план запроса, explain)
`log_slow_rate_limit` (выборка)НетДа
`log_slow_filter` (по типу запроса)НетДа
`slow_query_log_always_write_time`НетДа
Совместимость с `pt-query-digest`ПолнаяПолная
Формат вывода JSONДа (8.0.14+)Нет (использует текст)

Параметры log_slow_verbosity и log_slow_rate_limit в MariaDB особенно ценны в высоконагруженных производственных средах, где само по себе ведение журнала каждого медленного запроса может стать источником снижения производительности.

Шаг 1: Найдите файл конфигурации

MySQL и MariaDB считывают конфигурацию из разных путей по умолчанию в зависимости от дистрибутива и метода установки.

MySQL:

    /etc/my.cnf (RPM-based: RHEL, CentOS, AlmaLinux, Rocky Linux)
    /etc/mysql/my.cnf (Debian/Ubuntu)
    /etc/mysql/mysql.conf.d/mysqld.cnf (Ubuntu с пакетом mysql-server)
    
    MariaDB:
    
    /etc/my.cnf.d/server.cnf (RPM-based)
    /etc/mysql/mariadb.conf.d/50-server.cnf (Debian/Ubuntu)
    /etc/mysql/mariadb.cnf (более старые макеты Debian)
    
    Если вы не уверены, какой файл активен, запросите информацию у запущенного процесса:
    mysqld --verbose --help 2>/dev/null | grep -A1 "Default options"
    Это выводит точный упорядоченный список файлов, которые демон читает при запуске, включая все директории !includedir.
    Откройте основной файл конфигурации в предпочитаемом редакторе:
    sudo nano /etc/my.cnf
    Шаг 2: Добавьте директивы журнала медленных запросов в [mysqld]
    Все параметры журнала медленных запросов относятся к разделу [mysqld]. Если раздел не существует, создайте его в начале файла.
    [mysqld]
    # Core slow query log settings
    slow_query_log          = 1
    slow_query_log_file     = /var/log/mysql/slow-query.log
    long_query_time         = 1
    
    # Log queries that skip index usage entirely
    log_queries_not_using_indexes = 1
    
    # Avoid flooding the log with index warnings on low-traffic tables
    min_examined_row_limit  = 100
    
    # Log slow administrative statements (ALTER TABLE, OPTIMIZE TABLE, etc.)
    log_slow_admin_statements = 1
    Описание параметров:
    
    slow_query_log = 1 — активирует функцию; установите 0 для отключения без удаления блока
    slow_query_log_file — абсолютный путь к файлу журнала; пользователь процесса MySQL/MariaDB (mysql) должен иметь права на запись в родительский каталог
    long_query_time = 1 — порог в секундах, принимает десятичные значения (например, 0.5 для 500 мс); значение по умолчанию 10 секунд почти всегда слишком мягкое для веб-приложений
    log_queries_not_using_indexes — записывает запросы с полным сканированием независимо от long_query_time; используйте в сочетании с min_examined_row_limit для подавления шума от небольших таблиц
    min_examined_row_limit — запрос должен проверить не менее указанного количества строк, чтобы попасть в журнал при использовании log_queries_not_using_indexes; предотвращает засорение журнала тривиальными поисками по одной строке
    log_slow_admin_statements — фиксирует операции на уровне схемы, блокирующие таблицы, которые часто упускаются из виду как источники задержек
    
    Специфичные для MariaDB дополнения, которые стоит включить в производственной среде:
    # MariaDB only — extended per-query statistics in the log
    log_slow_verbosity      = query_plan,explain
    
    # MariaDB only — log only 1 in every N qualifying queries (rate limiting)
    log_slow_rate_limit     = 10
    log_slow_verbosity = query_plan,explain добавляет план выполнения оптимизатора непосредственно в каждую запись журнала, устраняя необходимость повторного запуска EXPLAIN вручную — что значительно экономит время при диагностике запросов, которые появляются только при производственных шаблонах нагрузки.
    Шаг 3: Создайте файл журнала и установите права доступа
    Если целевой каталог не существует, создайте его и назначьте владельца перед перезапуском службы. Пропуск этого шага — одна из наиболее распространённых причин, по которой журнал медленных запросов молча не активируется.
    sudo mkdir -p /var/log/mysql
    sudo touch /var/log/mysql/slow-query.log
    sudo chown mysql:mysql /var/log/mysql/slow-query.log
    sudo chmod 640 /var/log/mysql/slow-query.log
    На системах с принудительным применением SELinux (RHEL, CentOS, AlmaLinux) необходимо также правильно установить контекст файла:
    sudo semanage fcontext -a -t mysqld_log_t "/var/log/mysql(/.*)?"
    sudo restorecon -Rv /var/log/mysql
    Если не установить правильный контекст SELinux, демон успешно запустится, но молча пропустит запись в файл журнала — неприятный крайний случай, который не производит очевидных ошибок в /var/log/messages.
    Шаг 4: Перезапустите службу базы данных
    Примените изменения конфигурации, перезапустив службу. В дистрибутивах на основе systemd (стандарт на любом современном Linux-сервере):
    # MySQL
    sudo systemctl restart mysqld
    
    # MariaDB
    sudo systemctl restart mariadb
    На более старых системах на основе init.d:
    # MySQL
    sudo service mysqld restart
    
    # MariaDB
    sudo service mariadb restart
    После перезапуска убедитесь, что служба запустилась корректно:
    sudo systemctl status mysqld    # or mariadb
    sudo journalctl -u mysqld -n 50 --no-pager
    Любая ошибка конфигурации в my.cnf предотвратит запуск и отобразится в выводе журнала.
    Шаг 5: Включите журнал медленных запросов во время выполнения (без перезапуска)
    Для производственных серверов, где перезапуск нежелателен, MySQL и MariaDB поддерживают динамическое включение журнала медленных запросов через SET GLOBAL. Изменения, внесённые таким образом, вступают в силу немедленно, но не сохраняются после перезапуска службы, если они также не записаны в my.cnf.
    SET GLOBAL slow_query_log = 'ON';
    SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
    SET GLOBAL long_query_time = 1;
    SET GLOBAL log_queries_not_using_indexes = 1;
    SET GLOBAL min_examined_row_limit = 100;
    Это правильный подход для экстренной диагностики на работающей системе — включите его, соберите 15–30-минутный образец в период пиковой нагрузки, затем отключите, не затрагивая файл конфигурации и не перезапуская демон.
    Шаг 6: Проверьте конфигурацию
    Подключитесь к клиенту MySQL или MariaDB:
    mysql -u root -p
    Затем выполните поиск по таблице системных переменных:
    SHOW VARIABLES LIKE '%slow_query%';
    SHOW VARIABLES LIKE 'long_query_time';
    SHOW VARIABLES LIKE 'log_queries_not_using_indexes';
    Ожидаемый вывод для корректно настроенного экземпляра:
    +-------------------------------+-------------------------------+
    | Variable_name                 | Value                         |
    +-------------------------------+-------------------------------+
    | slow_query_log                | ON                            |
    | slow_query_log_file           | /var/log/mysql/slow-query.log |
    +-------------------------------+-------------------------------+
    
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | long_query_time | 1.000 |
    +-----------------+-------+
    
    +-------------------------------+-------+
    | Variable_name                 | Value |
    +-------------------------------+-------+
    | log_queries_not_using_indexes | ON    |
    +-------------------------------+-------+
    Вы также можете подтвердить, что в журнал ведётся запись, проверив счётчик медленных запросов:
    SHOW GLOBAL STATUS LIKE 'Slow_queries';
    Этот счётчик увеличивается каждый раз, когда запрос превышает long_query_time, независимо от того, активно ли ведение журнала в файл — это полезно для подтверждения того, что медленные запросы действительно происходят, прежде чем тратить время на анализ пустого файла журнала.
    Шаг 7: Чтение и интерпретация необработанного журнала
    Используйте tail для мониторинга журнала в реальном времени во время нагрузочного теста или в период пиковой нагрузки:
    sudo tail -f /var/log/mysql/slow-query.log
    Типичная запись журнала выглядит следующим образом:
    # Time: 2024-10-11T12:45:23.489187Z
    # User@Host: app_user[app_user] @ 10.0.1.45 []  Id: 1042
    # Query_time: 4.561529  Lock_time: 0.000115  Rows_sent: 1  Rows_examined: 847293
    # Bytes_sent: 512
    SET timestamp=1697030723;
    SELECT * FROM orders WHERE customer_email = 'user@example.com' ORDER BY created_at DESC;
    Что означает каждое поле:
    
    Query_time — общее время выполнения по настенным часам в секундах
    Lock_time — время ожидания получения блокировок таблиц или строк; высокое соотношение Lock_time к Query_time указывает на конкуренцию, а не на отсутствующий индекс
    Rows_sent — строки, возвращённые клиенту
    Rows_examined — строки, которые механизм хранения просканировал для получения результата; соотношение Rows_examined / Rows_sent выше 100:1 является явным признаком отсутствующего или плохо избирательного индекса
    Bytes_sent — присутствует в MariaDB с расширенной детализацией; полезно для выявления запросов, возвращающих излишне большие наборы результатов
    
    В приведённом примере запрос проверил 847 293 строки, чтобы вернуть 1 строку. Добавление индекса на customer_email сократит Rows_examined приблизительно до 1, уменьшив время выполнения с 4,5 секунды до субмиллисекундного.
    Шаг 8: Анализ журнала с помощью mysqldumpslow и pt-query-digest
    Чтение необработанного файла журнала непрактично в больших масштабах. Два инструмента агрегируют и ранжируют медленные запросы по общему влиянию.
    Использование mysqldumpslow (входит в комплект MySQL/MariaDB)
    # Top 10 queries by total execution time
    sudo mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log
    
    # Top 10 queries by average execution time
    sudo mysqldumpslow -s at -t 10 /var/log/mysql/slow-query.log
    
    # Top 10 queries by rows examined
    sudo mysqldumpslow -s r -t 10 /var/log/mysql/slow-query.log
    mysqldumpslow нормализует параметры запросов (заменяя литеральные значения на N или S), чтобы структурно идентичные запросы с разными значениями параметров группировались вместе — это необходимо для выявления часто встречающихся шаблонов.
    Использование pt-query-digest (Percona Toolkit — рекомендуется для производственной среды)
    # Install Percona Toolkit (Debian/Ubuntu)
    sudo apt-get install percona-toolkit
    
    # Install Percona Toolkit (RHEL/CentOS/AlmaLinux)
    sudo yum install percona-toolkit
    
    # Generate a full digest report
    sudo pt-query-digest /var/log/mysql/slow-query.log
    
    # Show only the top 5 queries by total time
    sudo pt-query-digest --limit 5 /var/log/mysql/slow-query.log
    
    # Output to a file for later review
    sudo pt-query-digest /var/log/mysql/slow-query.log > /tmp/slow_query_report.txt
    pt-query-digest формирует ранжированный отчёт, показывающий сигнатуру каждого запроса, общее время выполнения, среднее время, количество вызовов и процентильное распределение. Этот инструмент значительно мощнее mysqldumpslow и является стандартным инструментом, используемым профессиональными администраторами баз данных для анализа журналов медленных запросов.
    Шаг 9: Настройте ротацию журналов с помощью logrotate
    Без ротации журнал медленных запросов растёт бесконечно. На загруженном сервере с long_query_time, установленным на 1 секунду, файл может достигнуть нескольких гигабайт в течение нескольких дней.
    Создайте специальную конфигурацию logrotate:
    sudo nano /etc/logrotate.d/mysql-slow
    /var/log/mysql/slow-query.log {
        daily
        rotate 14
        missingok
        notifempty
        compress
        delaycompress
        sharedscripts
        postrotate
            /usr/bin/mysqladmin flush-logs 2>/dev/null || true
        endscript
    }
    Пояснение ключевых директив:
    
    rotate 14 — сохраняет 14 дней сжатых архивов; настройте в соответствии с вашим дисковым бюджетом и требованиями к аудиту
    compress / delaycompress — сжимает ротированные файлы в gzip, но откладывает сжатие на один цикл, чтобы избежать сжатия файла, который демон может ещё использовать
    postrotate — запускает mysqladmin flush-logs после ротации, что сигнализирует демону закрыть текущий дескриптор файла журнала и открыть новый; без этого MySQL/MariaDB продолжает записывать в переименованный файл до следующего перезапуска
    
    Выполните принудительную ротацию вручную для проверки конфигурации:
    sudo logrotate -f /etc/logrotate.d/mysql-slow
    Шаг 10: Отключите журнал медленных запросов, когда он больше не нужен
    Непрерывное ведение журнала медленных запросов с низким порогом (например, 0,5 секунды) на высоконагруженном сервере создаёт ощутимые накладные расходы на I/O. Отключите его после сбора достаточного количества данных:
    Через файл конфигурации (постоянно):
    [mysqld]
    slow_query_log = 0
    Затем перезапустите службу:
    sudo systemctl restart mysqld   # or mariadb
    Через переменную времени выполнения (немедленно, непостоянно):
    SET GLOBAL slow_query_log = 'OFF';
    Метод времени выполнения предпочтителен в производственные часы — он вступает в силу за миллисекунды без какого-либо простоя.
    Дополнительно: использование performance_schema в качестве дополнения
    Журнал медленных запросов фиксирует запросы, превышающие временной порог. Таблица performance_schema events_statements_summary_by_digest фиксирует агрегированную статистику для каждого отдельного шаблона запроса, независимо от времени выполнения. Совместное использование обоих инструментов даёт полную картину.
    SELECT
        DIGEST_TEXT,
        COUNT_STAR,
        ROUND(SUM_TIMER_WAIT / 1e12, 3)     AS total_time_sec,
        ROUND(AVG_TIMER_WAIT / 1e12, 6)     AS avg_time_sec,
        SUM_ROWS_EXAMINED,
        SUM_ROWS_SENT
    FROM performance_schema.events_statements_summary_by_digest
    ORDER BY SUM_TIMER_WAIT DESC
    LIMIT 10;
    Этот запрос выявляет 10 наиболее ресурсоёмких шаблонов запросов за всю историю операторов — включая быстрые запросы, которые выполняются миллионы раз и в совокупности доминируют по времени CPU, что журнал медленных запросов никогда не зафиксирует.
    Особенности хостинговой среды
    Оптимальный порог long_query_time во многом зависит от роли сервера и профиля ресурсов:
    
    Среды общего хостинга — как правило, нет прямого доступа к my.cnf; используйте SET GLOBAL, если хостинг-провайдер предоставляет привилегию SUPER или SYSTEM_VARIABLES_ADMIN, или запросите доступ к журналу медленных запросов через панель управления
    Среды VPS — полный root-доступ означает полный контроль над всеми параметрами конфигурации; установка VPS с cPanel предоставляет доступ к настройкам журнала медленных запросов через редактор конфигурации MySQL в WHM, который записывает непосредственно в my.cnf
  • Выделенные серверы — на выделенном сервере с высоконагруженной базой данных рассмотрите возможность установки long_query_time на уровне 0.1 секунд и использования log_slow_rate_limit (MariaDB) или выборки на уровне приложения для контроля объёма журнала
  • Аналитические рабочие нагрузки с ускорением GPU — на узлах GPU Hosting, выполняющих аналитические запросы к большим наборам данных, порог 5–10 секунд может быть уместным, поскольку длительные аналитические запросы являются ожидаемым поведением, а не дефектом

Если ваш стек приложений включает веб-интерфейс, управляемый через панель управления VPS, сопоставление временных меток журнала медленных запросов с временными метками журнала HTTP-доступа вашего приложения является эффективным методом отслеживания задержек базы данных до конкретных пользовательских запросов.

Практическая матрица решений: выбор правильного порога

СредаРекомендуемый `long_query_time``log_queries_not_using_indexes`Примечания
Разработка / тестирование0,1 – 0,5 сВКЛРаннее обнаружение регрессий; объём журнала приемлем
Производственная среда с низкой нагрузкой1,0 сВКЛ с `min_examined_row_limit = 500`Сбалансированное покрытие без избыточной нагрузки на I/O
Производственная среда с высокой нагрузкой0,5 – 1,0 сВКЛ с `log_slow_rate_limit = 10` (MariaDB)Ограничение частоты для управления дисковым I/O
OLAP / сервер отчётности5,0 – 10,0 сВЫКЛДлительные запросы ожидаемы; фокус на выбросах
Общий хостинг (ограниченный доступ)2,0 с (по умолчанию провайдера)Зависит от провайдераИспользуйте `performance_schema` как альтернативу

Технический контрольный список и ключевые выводы

Перед завершением расследования медленных запросов проверьте каждый из следующих пунктов:

  • Раздел [mysqld] в my.cnf содержит slow_query_log = 1, допустимый путь slow_query_log_file и long_query_time, соответствующий вашему профилю трафика
  • Файл журнала и его родительский каталог принадлежат системному пользователю mysql с правами на запись; на системах с SELinux контекст файла установлен как mysqld_log_t
  • SHOW VARIABLES LIKE '%slow_query%' подтверждает slow_query_log = ON и правильный путь к файлу после перезапуска службы
    SHOW GLOBAL STATUS LIKE 'Slow_queries' показывает ненулевой и увеличивающийся счётчик, подтверждая, что соответствующие запросы действительно происходят
    log_queries_not_using_indexes включён и сопряжён с min_examined_row_limit для предотвращения засорения журнала тривиальными поисками по одной строке
    log_slow_admin_statements включён для фиксации ALTER TABLE, OPTIMIZE TABLE и аналогичных DDL-операций, которые являются распространёнными источниками неожиданных блокировок таблиц
    Конфигурация logrotate настроена с хуком postrotate, вызывающим mysqladmin flush-logs
  • Вы запустили pt-query-digest или mysqldumpslow для агрегирования журнала и определили 3–5 наиболее ресурсоёмких запросов по общему времени выполнения
  • Каждый выявленный запрос был проанализирован с помощью EXPLAIN (или EXPLAIN ANALYZE в MySQL 8.0+) и добавлены соответствующие индексы или реструктурирована логика запроса
  • Журнал медленных запросов отключён или long_query_time повышен после завершения цикла оптимизации для минимизации текущих накладных расходов на I/O

Часто задаваемые вопросы

Влияет ли включение журнала медленных запросов на производительность базы данных?

При пороге 1 секунда и выше при типичной производственной нагрузке накладные расходы незначительны — обычно менее 1% от общего времени выполнения запросов. Накладные расходы становятся ощутимыми только при установке long_query_time ниже 0,1 секунды или при включении log_queries_not_using_indexes в схеме с множеством небольших неиндексированных таблиц. Используйте log_slow_rate_limit (MariaDB) или повысьте min_examined_row_limit для снижения этого эффекта.

Можно ли включить журнал медленных запросов без перезапуска MySQL или MariaDB?

Да. Используйте SET GLOBAL slow_query_log = 'ON' и SET GLOBAL long_query_time = 1 из любого сеанса клиента MySQL с привилегией SUPER или SYSTEM_VARIABLES_ADMIN. Изменение вступает в силу немедленно. Запишите те же значения в my.cnf, чтобы сделать их постоянными после перезапуска.

В чём разница между Query_time и Lock_time в журнале медленных запросов?

Query_time — это общее прошедшее время по настенным часам с момента получения сервером запроса до отправки последней строки клиенту. Lock_time — это часть этого общего времени, затраченная на ожидание получения блокировок таблиц или строк. Запрос с Lock_time, близким к Query_time, является проблемой конкуренции блокировок, а не проблемой индекса — исправление предполагает проектирование транзакций или уменьшение области блокировки, а не добавление индексов.

Почему мой файл журнала медленных запросов пуст, хотя slow_query_log = ON?

Наиболее распространённые причины: (1) ни один запрос ещё не превысил long_query_time — проверьте с помощью SHOW GLOBAL STATUS LIKE 'Slow_queries'; (2) путь к файлу журнала не существует или пользователь mysql не имеет прав на запись; (3) на системах с SELinux контекст файла неверен; (4) переменная slow_query_log_file указывает на другой путь, чем файл, который вы проверяете — подтвердите с помощью SHOW VARIABLES LIKE 'slow_query_log_file'.

Как найти единственный наиболее проблемный запрос в журнале медленных запросов?

Запустите pt-query-digest и отсортируйте по R/Call (проверенных строк на вызов) или Response time (общее накопленное время). Запрос в верхней части рейтинга Response time потребляет наибольшее совокупное время базы данных и должен быть первым объектом для анализа EXPLAIN и оптимизации индексов. Если pt-query-digest недоступен, используйте mysqldumpslow -s t -t 1 для извлечения единственного запроса с наибольшим общим временем.

15%

Сэкономьте 15% на всех хостинговых услугах

Проверьте свои навыки и получите скидку на любой тарифный план

Используйте код:

Skills
Начать