Статьи

max_allowed_packet и повреждение двоичного журнала в MySQL

[Эта статья была написана Мигелем Анхелем Ньето]

Сочетание   переменной max_allowed_packet и репликации в MySQL является распространенным источником головной боли. В двух словах, max_allowed_packet — это максимальный размер пакета сетевого протокола MySQL, который сервер может создать или прочитать. Он имеет значение по умолчанию 1 МБ (<= 5.6.5) или 4 МБ (> = 5.6.6) и максимальный размер 1 ГБ. Это добавляет некоторые ограничения в нашей среде репликации:

  • Главный сервер не должен записывать события в двоичный журнал больше, чем max_allowed_packet
  • Все ведомые в цепочке репликации должны иметь такой же max_allowed_packet, что и главный сервер

Иногда, даже следуя этим двум основным правилам, у нас могут возникнуть проблемы.

Например, существуют ситуации  (также называемые ошибками),  когда мастер записывает больше данных, чем предел max_allowed_packet, в результате чего подчиненные устройства перестают работать. Чтобы исправить это, Oracle создал новую переменную под названием  slave_max_allowed_packet . Эта новая переменная конфигурации, доступная из 5.1.64, 5.5.26 и 5.6.6, переопределяет значение max_allowed_packet для подчиненных потоков. Следовательно, независимо от значения max_allowed_packet потоки ведомых будут иметь ограничение в 1 ГБ, значение по умолчанию slave_max_allowed_packet. Хороший трюк, который работает как ожидалось.

Иногда даже с этим обходным путем мы можем получить ошибку max_allowed_packet на подчиненных серверах. Это означает, что существует пакет размером более 1 ГБ, чего не должно происходить в обычной ситуации. Зачем? Обычно это вызвано повреждением двоичного журнала. Давайте посмотрим на следующий пример:

Slave перестает работать со следующим сообщением:

Last_IO_Error: Получена фатальная ошибка 1236 от мастера при чтении данных из двоичного журнала: «превышена запись в журнале событий max_allowed_packet; Увеличьте max_allowed_packet на master '

Важной частью является «получение фатальной ошибки 1236 от мастера». Мастер не может прочитать событие, которое он записал в двоичный журнал несколько секунд назад. Чтобы проверить проблему, мы можем:

  • Используйте mysqlbinlog, чтобы прочитать двоичный журнал из позиции, в которой он потерпел неудачу с –start-position.

Это пример, взятый с наших  форумов Percona :

# 121003 5:22:26 идентификатор сервера 1 end_log_pos 398528
# Неизвестное событие
# на 398528
# 960218 6:48:44 id сервера 1813111337 end_log_pos 1835008
# Неизвестное событие
ОШИБКА: Ошибка в Log_event :: read_log_event (): «Событие слишком большое», data_len: 1953066613, event_type: 8
РАЗДЕЛИТЕЛЬ;
# Конец файла журнала

Проверьте размер события, 1953066613 байт. Или сообщения «Неизвестное событие». Там что-то явно не так. Другая обычная вещь для проверки — это идентификатор сервера, который иногда не соответствует реальному значению. В этом примере человек, который разместил двоичное событие журнала, подтвердил, что идентификатор сервера был неправильным.

  • Проверьте основной журнал ошибок.
[ОШИБКА] Ошибка в Log_event :: read_log_event (): «Событие слишком большое», data_len: 1953066613, event_type: 8

Опять же, событие больше, чем ожидалось. Ведущий и ведомый не могут ни читать, ни записывать, поэтому решение состоит в том, чтобы пропустить это событие в ведомом устройстве и повернуть журналы на главном. Затем используйте pt-table-checkum для проверки согласованности данных.

MySQL 5.6 включает контрольные суммы репликации, чтобы избежать проблем с повреждениями журнала. Вы можете прочитать больше об этом в  блоге Стефана .

Вывод

Ошибки на подчиненных серверах в отношении max_allowed_packet могут быть вызваны разными причинами. Хотя повреждение двоичного журнала не является распространенным явлением, его стоит проверить, если у вас закончились идеи.