Статьи

MySQL терпит крах: точка зрения инженера службы поддержки

В MySQL QA Episode # 12 « MySQL — это сбой, и что теперь? », Роул продемонстрировал, как собирать информацию о сбоях, которая поможет Percona выяснить, в чем заключается проблема, с которой вы столкнулись, и устранить ее.

Как инженер поддержки я (Света) очень рад видеть этот пост — но как человек, который лучше понимает написание, чем запись — я хотел бы получить ту же информацию в текстовом виде. Мы обсудили это и решили сделать совместную запись в блоге. Следовательно, этот пост:)

Если вы еще не видели видео или у вас нет опыта работы с GDB, основными файлами и сбоями, я настоятельно рекомендую сначала посмотреть его.

Как только вы поймете, почему происходят сбои, что делать после того, как это произойдет в вашей среде, и как открыть  проблему поддержки  и / или отчет об ошибке , вы готовы к следующему шагу: какую информацию вам нужно предоставить ? Обратите внимание, что чем более полную и всестороннюю информацию вы предоставляете, тем быстрее будет проходить процесс оценки и возможного исправления — это беспроигрышная ситуация!

Сначала нам нужен файл журнала ошибок MySQL. Если возможно, пришлите нам полный файл журнала ошибок. Часто пользователям нравится отправлять только ту часть, которую они считают релевантной, но файл журнала ошибок может содержать другую информацию, записанную до того, как произошел сбой. Например, записи о повреждениях таблиц, недостатке места на диске, проблемах со словарем InnoDB и т. Д.

Если ваш журнал ошибок довольно большой, обратите внимание, что он очень хорошо сжимается с помощью стандартного инструмента сжатия, такого как gzip. Если по какой-либо причине вы не можете отправить полный файл журнала ошибок, отправьте все строки, написанные после слов «mysqld: ready for connection» (как видно в последний раз перед фактическим сбоем), до конца файла журнала ошибок ( Кроме того, вы также можете искать строки, начинающиеся со слова «Версия:»). Или, если вы используете сценарии (или mysqld_safe), которые автоматически перезапускают MySQL Server в случае аварии, очевидно, пожалуйста, найдите один предыдущий запуск сервера после сбоя.

Пример, который включает автоматический перезапуск, как упомянуто выше:

2015-08-03 14:24:03 9911 [Note] /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld: ready for connections.
Version: '5.6.25-73.1-log'  socket: '/tmp/mysql_sandbox21690.sock'  port: 21690  Percona Server (GPL), Release 73.1, Revision 07b797f
2015-08-03 14:24:25 7f5b193f9700 InnoDB: Buffer pool(s) load completed at 150803 14:24:25
11:25:12 UTC - mysqld got signal 4 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.
Please help us make Percona Server better by reporting any
bugs at http://bugs.percona.com/
key_buffer_size=268435456
read_buffer_size=131072
max_used_connections=1
max_threads=216
thread_count=1
connection_count=1
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 348059 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x0
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 = 0 thread_stack 0x40000
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(my_print_stacktrace+0x2e)[0x8dd38e]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(handle_fatal_signal+0x491)[0x6a5dc1]
/lib64/libpthread.so.0(+0xf890)[0x7f5c58ac8890]
/lib64/libc.so.6(__poll+0x2d)[0x7f5c570fbc5d]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(_Z26handle_connections_socketsv+0x1c2)[0x5f64c2]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(_Z11mysqld_mainiPPc+0x1b5d)[0x5fd87d]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f5c57040b05]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld[0x5f10fd]
You may download the Percona Server operations manual by visiting
http://www.percona.com/software/percona-server/. You may find information
in the manual which will help you identify the cause of the crash.
150803 14:25:12 mysqld_safe Number of processes running now: 0
150803 14:25:12 mysqld_safe mysqld restarted
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld: /lib64/libssl.so.1.0.0: no version information available (required by /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld)
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld: /lib64/libcrypto.so.1.0.0: no version information available (required by /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld)
2015-08-03 14:25:12 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2015-08-03 14:25:12 0 [Note] /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld (mysqld 5.6.25-73.1-log) starting as process 10038 ...
2015-08-03 14:25:12 10038 [Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 50005)
2015-08-03 14:25:12 10038 [Warning] Buffered warning: Changed limits: max_connections: 214 (requested 10000)
2015-08-03 14:25:12 10038 [Warning] Buffered warning: Changed limits: table_open_cache: 400 (requested 4096)
2015-08-03 14:25:12 10038 [Note] Plugin 'FEDERATED' is disabled.
2015-08-03 14:25:12 10038 [Note] InnoDB: Using atomics to ref count buffer pool pages
2015-08-03 14:25:12 10038 [Note] InnoDB: The InnoDB memory heap is disabled
2015-08-03 14:25:12 10038 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2015-08-03 14:25:12 10038 [Note] InnoDB: Memory barrier is not used
2015-08-03 14:25:12 10038 [Note] InnoDB: Compressed tables use zlib 1.2.3
2015-08-03 14:25:12 10038 [Note] InnoDB: Using Linux native AIO
2015-08-03 14:25:12 10038 [Note] InnoDB: Using CPU crc32 instructions
2015-08-03 14:25:12 10038 [Note] InnoDB: Initializing buffer pool, size = 4.0G
2015-08-03 14:25:13 10038 [Note] InnoDB: Completed initialization of buffer pool
2015-08-03 14:25:13 10038 [Note] InnoDB: Highest supported file format is Barracuda.
2015-08-03 14:25:13 10038 [Note] InnoDB: The log sequence numbers 514865622 and 514865622 in ibdata files do not match the log sequence number 514865742 in the ib_logfiles!
2015-08-03 14:25:13 10038 [Note] InnoDB: Database was not shutdown normally!
2015-08-03 14:25:13 10038 [Note] InnoDB: Starting crash recovery.
2015-08-03 14:25:13 10038 [Note] InnoDB: Reading tablespace information from the .ibd files...
2015-08-03 14:25:14 10038 [Note] InnoDB: Restoring possible half-written data pages
2015-08-03 14:25:14 10038 [Note] InnoDB: from the doublewrite buffer...
InnoDB: Last MySQL binlog file position 0 150866, file name mysql-bin.000006
2015-08-03 14:25:16 10038 [Note] InnoDB: 128 rollback segment(s) are active.
2015-08-03 14:25:16 10038 [Note] InnoDB: Waiting for purge to start
2015-08-03 14:25:16 10038 [Note] InnoDB:  Percona XtraDB (http://www.percona.com) 5.6.25-rel73.1 started; log sequence number 514865742
2015-08-03 14:25:16 7f67ceff9700 InnoDB: Loading buffer pool(s) from .//ib_buffer_pool
2015-08-03 14:25:16 10038 [Note] Recovering after a crash using mysql-bin
2015-08-03 14:25:16 10038 [Note] Starting crash recovery...
2015-08-03 14:25:16 10038 [Note] Crash recovery finished.
2015-08-03 14:25:17 10038 [Note] RSA private key file not found: /home/sveta/sandboxes/rsandbox_Percona-Server-5_6_25/master/data//private_key.pem. Some authentication plugins will not work.
2015-08-03 14:25:17 10038 [Note] RSA public key file not found: /home/sveta/sandboxes/rsandbox_Percona-Server-5_6_25/master/data//public_key.pem. Some authentication plugins will not work.
2015-08-03 14:25:17 10038 [Note] Server hostname (bind-address): '127.0.0.1'; port: 21690
2015-08-03 14:25:17 10038 [Note]   - '127.0.0.1' resolves to '127.0.0.1';
2015-08-03 14:25:17 10038 [Note] Server socket created on IP: '127.0.0.1'.
2015-08-03 14:25:17 10038 [Warning] 'proxies_priv' entry '@ root@thinkie' ignored in --skip-name-resolve mode.
2015-08-03 14:25:17 10038 [Note] Event Scheduler: Loaded 0 events
2015-08-03 14:25:17 10038 [Note] /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld: ready for connections.
Version: '5.6.25-73.1-log'  socket: '/tmp/mysql_sandbox21690.sock'  port: 21690  Percona Server (GPL), Release 73.1, Revision 07b797f

Обычно файл журнала ошибок содержит фактический запрос, вызвавший сбой. Если это не так, и вы знаете запрос (например, если ваше приложение регистрирует ошибки / проблемы с запросами), отправьте нам этот запрос. Кроме того, если возможно, включите операторы CREATE TABLE для любых таблиц, упомянутых в запросе. Фактическая работа с запросом — это первое, что вы можете сделать, чтобы решить проблему: попробуйте выполнить этот запрос (на непроизводственном / тестовом сервере, который находится как можно ближе к вашему производственному серверу), чтобы убедиться, что он аварийно завершает работу. MySQL Server последовательно. Если это так, вы можете попытаться создать временный обходной путь, избегая такого рода запросов в вашем приложении.

Если у вас есть сомнения относительно того, какой запрос вызвал сбой, но включен ли общий журнал запросов, вы можете использовать утилиту parse_general_log.pl из percona-qa для создания потенциального тестового примера. Просто выполните:

$ sudo yum install bzr
$ cd ~
$ bzr branch lp:percona-qa
$ cp /path_that_contains_your_general_log/your_log_file.sql ~
$ ~/percona-qa/parse_general_log.pl -i./your_log_file.sql -o./output.sql

И затем выполните output.sql для mysqld на непроизводственном тестовом сервере, чтобы проверить, не произойдет ли сбой. Кроме того, вы можете отправить нам файл output.sql (при условии, что это разрешено политикой конфиденциальности вашей компании и т. Д.). Если вы хотите еще больше сократить тестовый набор, см. QA Episode # 7, посвященный сокращению тестовых случаев .

Следующее, что нам нужно, это обратный след. Обычно у вас есть простая обратная трассировка, отображаемая в журнале ошибок сразу после сбоя. Пример (извлеченный из журнала ошибок) того, как это выглядит:

stack_bottom = 0 thread_stack 0x40000
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(my_print_stacktrace+0x2e)[0x8dd38e]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(handle_fatal_signal+0x491)[0x6a5dc1]
/lib64/libpthread.so.0(+0xf890)[0x7f5c58ac8890]
/lib64/libc.so.6(__poll+0x2d)[0x7f5c570fbc5d]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(_Z26handle_connections_socketsv+0x1c2)[0x5f64c2]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(_Z11mysqld_mainiPPc+0x1b5d)[0x5fd87d]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f5c57040b05]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld[0x5f10fd]

Обратите внимание, что вышеупомянутая обратная трассировка искажена. Вы можете отправить нам файл следующим образом (мы можем разобрать его). Тем не менее, если вы хотите работать с ним более комфортно, вы можете разобраться с ним с помощью утилиты c ++ filt:

sveta@linux-85fm:~/sandboxes/rsandbox_Percona-Server-5_6_25> cat master/data/msandbox.err | c++filt
...
terribly wrong...
stack_bottom = 0 thread_stack 0x40000
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(my_print_stacktrace+0x2e)[0x8dd38e]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(handle_fatal_signal+0x491)[0x6a5dc1]
/lib64/libpthread.so.0(+0xf890)[0x7f5c58ac8890]
/lib64/libc.so.6(__poll+0x2d)[0x7f5c570fbc5d]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(handle_connections_sockets()+0x1c2)[0x5f64c2]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld(mysqld_main(int, char**)+0x1b5d)[0x5fd87d]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f5c57040b05]
/home/sveta/SharedData/Downloads/5.6.25/bin/mysqld[0x5f10fd]
...

Теперь обратная трассировка выглядит намного приятнее. При отправке нам отчетов об ошибках, пожалуйста, не используйте на них c ++ filta перед отправкой. У нас есть список известных ошибок, и для сканирования списка известных ошибок нам нужно получить журнал ошибок без изменений.

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

Примечание.  Обратите внимание: всегда полезно установить пакет debuginfo (например, Percona-Server-56-debuginfo.x86_64 из репозитория Percona). Этот пакет предоставляет символы отладки для сервера Percona (существуют аналогичные пакеты для других дистрибутивов) и гарантирует, что трассировки стека будут более читабельными и содержат больше информации. Важно убедиться, что у вас правильная версия пакета и т. Д., Поскольку символы отличаются для каждой версии mysqld. Если вы установили Percona Server из нашего репозитория, вы можете просто установить пакет debuginfo, версия будет правильной, и пакет будет автоматически обновляться при обновлении Percona Server.

По умолчанию сервер MySQL не создает файлы ядра. Чтобы сделать это, вы можете следовать инструкциям из « Шпаргалки GDB » (страница 2 под заголовком «Шпаргалка Core Files»). Короче говоря:

  • Добавьте опцию core-file в раздел [mysqld] вашего конфигурационного файла
  • Настройте параметры своей ОС, чтобы она позволила mysqld создавать файлы ядра, как описано в шпаргалке.
    echo "core.%p.%e.%s" > /proc/sys/kernel/core_pattern
    ulimit -c unlimited
    sudo sysctl -w fs.suid_dumpable=2

    Примечание: некоторые системы используют «ядро» вместо «fs»: вместо этого используйте kernel.suid_dumpable = 2, если вы получаете ключ или файл предупреждений / ошибок.

  • Перезагрузите сервер MySQL

Помимо файла ядра, который генерируется сервером MySQL, вы также можете настроить операционную систему для вывода файла ядра. Это два разных файла ядра (для одного сбоя двоичного файла mysqld), и объем содержащейся в них информации может отличаться. Процедура выше показывает, как настроить один только для MySQL Server.

Если вам нравится, что ваша операционная система также создает дамп основного файла, посмотрите видео MySQL QA Episode # 12 . Также обратите внимание, что изменение настроек ulimit и fs.suid_dumpable может повлиять на безопасность вашей системы. Пожалуйста, прочитайте больше об этих опциях онлайн, прежде чем использовать их или оставить их навсегда в производственной системе.

После создания файла ядра вы можете использовать утилиту GDB для отладки файла ядра (также называемого «coredump»). GDB позволяет вам лучше разрешать обратные трассировки (также называемые «стековыми трассами» или «стеками»), например, принимая обратную трассировку всех потоков, а не только сбойных потоков. Это, конечно, лучше, чем единственная обратная трассировка, доступная в файле журнала ошибок. Чтобы использовать GDB, вам нужно сначала запустить его:

gdb /path_to_mysqld /path_to_core

/ path_to_core обычно является вашим каталогом данных (для coredumps, созданным mysqld в результате использования параметра –core-file в вашем файле my.cnf), или иногда в том же каталоге, где находится аварийный двоичный файл (для coredumps, создаваемых ОС ) — хотя вы можете указать альтернативное фиксированное местоположение для OS Coredumps в качестве шпаргалки. Обратите внимание, что сгенерированные ОС дампы иногда пишутся с очень небольшим количеством привилегий, поэтому вам, возможно, придется использовать chown / chmod / sudo для доступа к нему.

Как только вы попали в GDB, и все выглядит нормально, выполните команды bt (backtrace) и bt thread apply all (get backtrace для всех потоков), чтобы получить трассировки стека. bt должно более или менее соответствовать обратному следу, замеченному в журнале ошибок, но иногда это может отличаться.

Для нас в идеале вы должны выполнить следующие команды в GDB (как видно из шпаргалки ):

set trace-commands on
set pagination off
set print pretty on
set print array on
set print array-indexes on
set print elements 4096
set logging file gdb_standard.txt
set logging on
thread apply all bt
set logging off
set logging file gdb_full.txt
set logging on
thread apply all bt full

После того, как вы запустите эти команды и создадите (выйдите из GDB), отправьте нам файлы ./gdb_standard.txt и ./gdb_full.txt.

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

Однако файл ядра без mysqld бесполезен, поэтому, пожалуйста, добавьте двоичный файл mysqld вместе с файлом ядра. Если вы используете наши скомпилированные двоичные файлы, вы также можете указать точный пакет и имя файла, который вы скачали, но если вы используете самоскомпилированную версию сервера, двоичный файл mysqld необходим для разрешения обратной трассировки и другой необходимой информации (например, varialbes). ) из вашего основного файла. Вообще говоря, проще просто отправить mysqld.

Также было бы неплохо, если бы вы отправили нам библиотечные файлы, которые динамически связаны с используемым вами mysqld. Вы можете получить их, используя инструмент под названием ldd_files.sh из пакета percona-qa . Просто создайте временный каталог, скопируйте в него двоичный файл mysqld и запустите на нем инструмент:

sveta@thinkie:~/tmp> wget http://bazaar.launchpad.net/~percona-core/percona-qa/trunk/download/head:/ldd_files.sh-20150713030145-8xdk0llrd3skfsan-1/ldd_files.sh
sveta@thinkie:~/tmp> mkdir tmp
sveta@thinkie:~/tmp> cd tmp/
sveta@thinkie:~/tmp/tmp> cp /home/sveta/SharedData/Downloads/5.6.25/bin/mysqld . # Copy of your mysqld
sveta@thinkie:~/tmp/tmp> ../ldd_files.sh mysqld # Run the tool on it
cp: cannot stat ‘./mysqld: /lib64/libssl.so.1.0.0: no version information available’: No such file or directory # Ignore
cp: cannot stat ‘./mysqld: /lib64/libcrypto.so.1.0.0: no version information available’: No such file or directory # Ignore
sveta@thinkie:~/tmp/tmp> ls
ld-linux-x86-64.so.2 libaio.so.1 libcrypto.so.1.0.0 libcrypt.so.1 libc.so.6 libdl.so.2 libgcc_s.so.1 libm.so.6 libpthread.so.0 librt.so.1 libssl.so.1.0.0 libstdc++.so.6 libz.so.1 mysqld # Files to supply in combination with mysqld

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

Резюме

Если вы попали в аварию, пожалуйста, пришлите нам (в порядке предпочтения, но еще лучше «все это»):

  • Файл журнала ошибок (пожалуйста, отправьте его без изменений — т. Е. До выполнения фильтра C ++ — который позволяет нам сканировать известные ошибки)
  • Сбой запроса (из журналов вашего приложения и / или извлечен из основного файла — см. Сообщение в блоге об извлечении запроса)

    • Пожалуйста, включите соответствующие операторы CREATE TABLE
  • Разрешенная обратная трассировка (и / или предпочтительно файлы ./gdb_standard.txt и ./gdb_full.txt)
  • Основной файл вместе с двоичным файлом mysqld и, предпочтительно, с файлами ldd.

Спасибо!

Примечание редактора: Первоначально появилось в блоге Percona, написанном  Светой Смирновой  и  Роэлем Ван де Пааром .