Предыстория: в середине лета наша команда DBA взяла на поддержку больше 30 серверов баз данных MySQL одного известного в России маркетплейса. Знакомство было интересным, масса нестандартных задач. Все благодаря тому, что обслуживанием серверов до нашего вмешательства занимались мало или не занимались в принципе, а в случае возникновения проблем заливали сервера ресурсами.
В первую очередь я хочу рассказать о проблеме, с которой столкнулась наша команда во время проведения аудита серверов баз данных. Забегая вперед, до конца не удалось разгадать всех премудростей этого чудного бага (но мы стараемся).
В группе из пятнадцати серверов СУБД, где находились базы данных ПВЗ, отличительно выделялись шесть, по хронологии событий, созданных позже остальных, на которых служба mysqld ежедневно отправлялась в рестарт в хаотичном порядке на протяжении длительного времени. Сильных проблем это не доставляло, но это можно считать большой удачей. Если бы кластер баз данных развалился, больше 100 ПВЗ не смогли бы работать продолжительное время (представьте какой хаос мог бы начаться в обществе ?). Но служба заново запускалась и продолжала работать до следующего перезапуска, оставляя в логах пугающие следы:
18:50:29 UTC - mysqld got signal 11;
Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware.
Build ID: Not Available
Server Version: 8.0.30-22 Percona Server (GPL), Release 22, Revision 7e301439b65
Thread pointer: 0x7f89deba9090
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7f8995ce2d10 thread_stack 0x40000
/usr/sbin/mysqld(my_print_stacktrace(unsigned char const*, unsigned long)+0x41) [0x20bedb1]
/usr/sbin/mysqld(print_fatal_signal(int)+0x30f) [0x11697af]
/usr/sbin/mysqld(handle_fatal_signal+0xd5) [0x1169895]
/lib64/libpthread.so.0(+0x12cf0) [0x7f90ad7abcf0]
/lib64/libc.so.6(+0xcd007) [0x7f90abbd9007]
/usr/sbin/mysqld(Item_field::Item_field(YYLTYPE const&, char const*, char const*, char const*)+0x84) [0xcff284]
/usr/sbin/mysqld(PTI_simple_ident_q_3d::itemize(Parse_context*, Item**)+0xfb) [0x130c5eb]
/usr/sbin/mysqld(PTI_expr_with_alias::itemize(Parse_context*, Item**)+0x38) [0x1309928]
/usr/sbin/mysqld(PT_select_item_list::contextualize(Parse_context*)+0x86) [0xec1c06]
/usr/sbin/mysqld(PT_query_specification::contextualize(Parse_context*)+0x95) [0xec1595]
/usr/sbin/mysqld(PT_query_expression::contextualize(Parse_context*)+0x97) [0xebfc47]
/usr/sbin/mysqld(PT_select_stmt::make_cmd(THD*)+0x5b) [0xeb954b]
/usr/sbin/mysqld(LEX::make_sql_cmd(Parse_tree_root*)+0x2b) [0xfbb32b]
/usr/sbin/mysqld(THD::sql_parser()+0x5e) [0xf6179e]
/usr/sbin/mysqld(parse_sql(THD*, Parser_state*, Object_creation_ctx*)+0x12b) [0xfdf94b]
/usr/sbin/mysqld(dispatch_sql_command(THD*, Parser_state*, bool)+0x2ed) [0xfe635d]
/usr/sbin/mysqld(dispatch_command(THD*, COM_DATA const*, enum_server_command)+0xefe) [0xfe7a0e]
/usr/sbin/mysqld(do_command(THD*)+0x282) [0xfe9bf2]
/usr/sbin/mysqld() [0x1159850]
/usr/sbin/mysqld() [0x2613cf9]
/lib64/libpthread.so.0(+0x81cf) [0x7f90ad7a11cf]
/lib64/libc.so.6(clone+0x43) [0x7f90abb45e73]
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Проверив наличие резервных копий и убедившись, что они есть))) Мы отправились на поиски причин и скорейшего их исправления, дабы не оказаться у разбитого корыта с кучей потерянных или не консистентных данных, которые бы пришлось спасать.
Причин данной проблемы может быть множество, например:
Нехватка оперативной памяти. Если mysqld использует слишком много памяти, система может отправить сигнал 11. Это может произойти, если mysqld неправильно настроен, выполняет большое количество запросов или просто из-за банальной любви СУБД ко всей оперативной памяти.
Недостаток места на диске. Если в системе заканчивается место на диске, это также может вызвать получение сигнала 11. Например, если mysqld использует большое количество временного места на диске или в системе заканчивается место на диске.
Аппаратный сбой. Возникает во время работы под влиянием внешних факторов: высокой температуры, скачков питающего напряжения и других.
К сожалению, ни одна из этих причин не являлась виновником в нашем конкретном случае. После изысканий я определил, что выходят из строя только сервера с версией 8.0.30-22 Percona Server (GPL) на ОС AlmaLinux 8.9 (Midnight Oncilla).
На официальном ресурсе Percona есть статья про этот баг, поэтому подробно углубляться в нее не будем, перейдем сразу к тому, как избавиться от этого недуга.
Единственно верной рекомендацией от разработчиков Percona является обновление версии MySQL. К большому сожалению репозиторий Alma Linux 8 включает в себя только версию 8.0.30-22 Percona Server (GPL), поэтому при обновлении придется воспользоваться сторонним репозиторием.
И так, к делу: обновляем Percona-server, спасаем MySQL
Шаг 1. Загружаем основной пакет из репозитория Percona (пакеты могут отличаться в зависимости от версии ОС)
Пакет клиента:
$ wget http://repo.percona.com/pdps-8.0.37/yum/release/8/RPMS/x86_64/percona-server-client-8.0.37-29.1.el8.x86_64.rpm
Пакет сервера:
$ wget http://repo.percona.com/pdps-8.0.37/yum/release/8/RPMS/x86_64/percona-server-server-8.0.37-29.1.el8.x86_64.rpm
Пакет для сбора телеметрии и отправки ее в службу Percona Telemetry:
$ wget http://repo.percona.com/pdps-8.0.37/yum/release/8/RPMS/x86_64/percona-telemetry-agent-1.0.1-1.el8.x86_64.rpm
Шаг 2. Останавливаем службу MySQL
$ sudo systemctl stop mysqld.service
Шаг 3. Устанавливаем пакеты с помощью rpm
$ sudo rpm -Uvh percona-telemetry-agent-1.0.1-1.el8.x86_64.rpm
$ sudo rpm -Uvh percona-server-client-8.0.37-29.1.el8.x86_64.rpm
$ sudo rpm -Uvh percona-server-server-8.0.37-29.1.el8.x86_64.rpm
Шаг 4. Проверяем конфигурационный файл на предмет устаревших параметров и заменяем их на новые. Лично для меня это были следующие значения:
The syntax 'slave_exec_mode' -> 'replica_exec_mode'
The syntax 'slave_skip_errors' -> 'replica_skip_errors'
The syntax 'log_slave_updates' -> 'log_replica_updates'
The syntax 'innodb_log_file_size/innodb_log_files_in_group' -> 'innodb_redo_log_capacity'
Другие конфигурационные параметры, которые устарели, можно найти в логе, после запуска сервера MySQL.
Шаг 5. Запускаем службу MySQL
$ sudo systemctl start mysqld.service
Шаг 6. Проверяем версии сервера и клиента
Версия клиента:
$ mysql -v
Версия серверу, можно узнать подключившись к MySQL и выполнить запрос:
SELECT version();
После проделанных выше действий не было ни одного сбоя в работе СУБД на этих серверах, а также в процессе обновление затронуло другие сервера, на которых версия MySQL была 8.0.21-12.
P.S. Почему такое бывает и как не допустить подобных случаев?
Если у вас не завышенные требования к безотказности работы системы в целом, то для большинства эта проблема не будет заметной до тех пор пока не произойдет авария, и кластер баз данных не сможет собраться воедино после очередной перезагрузки (этого может и не произойти), но в высоконагруженных системах эта проблема может вызвать головную боль, поэтому следует сразу принять меры и обновить MySQL до стабильной версии.
Как избежать таких неожиданных сюрпризов?
Читать bug-report MySQL и Percona, вовремя актуализировать версии, мониторить производительность серверов баз данных и делать резервные копии.
Всем добра!