Перейти к содержимому

MySQL Query Error - причины по убыванию частоты

Страница отдаёт «MySQL Query Error» или «DB query error. Please try later»: соединение с базой есть, но конкретный запрос не выполнился.

Как проверить

Читаем полный текст ошибки в логе платформы:

Окно терминала
tail -n 40 /home/bitrix/www/bitrix/php_interface/dbconn_error.log 2>/dev/null
grep -iE 'mysql|query error' /var/log/php-fpm/error.log | tail -20
# полный текст запроса лежит в журнале, а не на странице у посетителя

На странице сообщение обрезано намеренно: полный запрос содержит данные, которые нельзя показывать посетителю. В логе он лежит целиком, вместе с кодом ошибки.

Смотрим состояние базы: место, соединения, блокировки:

SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
SHOW FULL PROCESSLIST; -- долгие запросы держат таблицы

Число соединений вплотную к пределу и длинный список процессов объясняют плавающие ошибки: в спокойное время тот же код работает.

Причины

  1. Дубль по уникальному ключу примерно 35% случаев

    ПризнакВ тексте ошибки код 1062 и слово Duplicate entry с именем индекса.

    ПроверкаЧитаем имя индекса из сообщения: оно называет таблицу и поле, по которому конфликт.

    Что делатьИщем существующую запись и обновляем её вместо вставки: у платформы для этого есть отдельные методы.

  2. Кончилось место на диске примерно 30% случаев

    ПризнакОшибки появились разом на всех страницах с записью, чтение работает.

    ПроверкаСмотрим свободное место и inode на разделе с базой и с сайтом.

    Что делатьЧистим резервные копии, бинарные логи и кеш, затем перезапускаем сервер базы.

  3. Упёрлись в предел соединений примерно 25% случаев

    ПризнакОшибки плавающие, приходят под нагрузкой, в тексте код 1040.

    ПроверкаСравниваем число активных соединений с пределом и смотрим список процессов.

    Что делатьУбираем долгие запросы и поднимаем предел соразмерно памяти: каждое соединение её потребляет.

  4. Повреждена таблица примерно 10% случаев

    ПризнакОшибка приходит всегда на одном и том же действии, в тексте имя одной таблицы.

    ПроверкаПроверяем названную таблицу штатной проверкой базы и читаем лог сервера базы.

    Что делатьВосстанавливаем таблицу, а при неудаче поднимаем её из копии: остальные при этом не трогаем.

Если ничего не помогло

Включаем протокол медленных и ошибочных запросов:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- секунда, чтобы поймать реальных виновников
SET GLOBAL log_output = 'TABLE'; -- пишем в таблицу, а не в файл

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

Проверяем таблицу, названную в ошибке:

CHECK TABLE b_iblock_element; -- имя берём из текста ошибки, а не наугад
REPAIR TABLE b_iblock_element; -- только для MyISAM, у InnoDB другой путь

Проверять всю базу подряд не нужно и вредно: операция блокирует таблицы. Работают только с той, что названа в сообщении.

Частые вопросы

Ошибка Duplicate entry по индексу seometa - что это?

Платформа пишет SEO-данные страницы и наткнулась на существующую запись с тем же ключом. Обычно это следы неудачного обмена или копирования элементов: конфликтующую запись находят по имени индекса и убирают.

Почему ошибка появляется только в корзине?

Корзина пишет в базу на каждое действие покупателя, и упирается в пределы первой. Сама она при этом исправна: смотреть надо место, соединения и блокировки.

Помогает ли перезапуск базы?

Временно и только при исчерпанных соединениях. Место, дубли и повреждения перезапуск не лечит, а на большой базе он ещё и занимает минуты.

Как отличить ошибку запроса от недоступности базы?

По тексту: «Query error» означает, что соединение есть и отклонён конкретный запрос, «Connect error» - что до сервера не достучались вовсе. Первое разбирают в логе платформы, второе на сервере.

Смежное

Первоисточник