Диагностика редко возникающих проблем сервера MySQL

Светлана Комарова

Светлана Комарова

Автор статьи. Системный администратор, Oracle DBA. Информационные технологии, интернет, телеком. Подробнее.

Поиск и решенение нетипичных проблем MySQLРедко возникающие проблемы MySQL, такие как случайный серверный стопор или мед­ленное выполнение запросов, могут портить диагностику. Самые вопиющие потери времени, которые мы встречали, были результатом фантомных проблем, возникающих только тогда, когда за системой никто не следил, при этом воспроизвести их не удавалось. Нам доводилось видеть, как люди тратят целые месяцы на борьбу с такими проблемами. В ходе этого некоторые специалисты устраняли неполадки ме­тодом проб и ошибок и иногда значительно ухудшали ситуацию, пытаясь случайным образом изменить настройки сервера и надеясь наткнуться на решение проблемы.



Старайтесь, насколько это возможно, избегать метода проб и ошибок. Такое устране­ние неполадок рискованно, поскольку результаты могут быть отрицательными и, как следствие, весь процесс окажется бесполезным и неэффективным. Если вы не можете понять, в чем проблема, возможно, вы неправильно выполняете измерения, делаете это в неправильном месте или не знаете, какие инструменты надо использовать. (Или последние могут отсутствовать — мы разработали ряд инструментов, предназначен­ных специально для увеличения прозрачности различных компонентов системы, от операционной системы до MySQL в целом.)

Чтобы проиллюстрировать необходимость отказаться от метода проб и ошибок, рас­смотрим несколько практических примеров решения некоторых редко возникающих проблем с производительностью баз данных MySQL.

  • Приложение выполняло утилиту curl для получения котировок обменных курсов от в разы более медленного внешнего сервиса.
  • Важные записи кэша исчезли из memcached, в результате чего приложение пере­полняло MySQL запросами на восстановление кэшированных элементов.
  • DNS-запросы синхронизировались случайным образом.
  • Кэш запросов периодически замораживал MySQL из-за конкуренции мьютексов или неэффективных внутренних алгоритмов удаления кэшированных запросов.
  • Ограничения масштабируемости InnoDB приводили к слишком длительной оптимизации плана запроса, если объем конкурентного доступа превышал некоторое пороговое значение.

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

Здесь мы закончим читать вам лекцию и начнем рассматривать подход и инструмен­ты, которые обычно используем для решения редко возникающих проблем.

 

Проблемы одиночного запроса или всего сервера?

У вас есть какие-либо доказательства существования проблемы? Если да, попробуйте определить, связана она с изолированным запросом или со всем сервером. Это важно для понимания того, куда двигаться в ходе ее решения. Если на сервере все работает плохо, а затем нормализуется, тогда медленно работающий запрос вряд ли является источни­ком проблемы. Большинство медленных запросов, скорее всего, сами стали жертвами какой-то другой проблемы. В то же время, если сервер в целом работает хорошо, а один запрос по какой-то причине выполняется медленно, следует внимательнее его изучить.

Проблемы с сервером возникают довольно часто. По мере появления в последние годы более мощного оборудования, когда 16-ядерные и более крупные серверы становятся нормой, ограничения масштабируемости MySQL на SMP-системы стали более заметными. Истоки большинства этих проблем кроются в более старых версиях, которые, к сожалению, все еще широко используются. У MySQL еще есть проблемы с масштабируемостью даже в более новых версиях, но они гораздо менее серьезны и намного реже встречаются, поскольку являются пограничными случаями. Это и хорошая, и плохая новость: хорошая, потому что вероятность столкнуться с ними невелика, и плохая, так как для их диагностики требуется больше знаний о внутренних функциях MySQL. Это также означает, что множество проблем можно решить, просто обновив MySQL.

Как определить, является ли проблема общей для сервера или ограничена единственным запросом? Существуют три простых метода для выяснения этого. Мы рассмотрим их далее.

 

Команда SHOW GLOBAL STATUS

Суть методики заключается в очень частой фиксации выборки SHOW GLOBAL STATUS, например один раз в секунду и при появлении проблемы, поиске пиков или провалов в показаниях счетчиков, таких как Threads_running, Threads_connected, Questions и Queries. Это простой, не затрагивающий сервера метод, который доступен любому пользователю (никаких специальных привилегий не требуется), а поэтому — отличный способ больше узнать о природе проблемы, не затрачивая много времени. Приведем пример команды и вывода:

$ mysqladmin ext -i1 | awk '
    /Queries/{q=$4-qp;qp=$4}
    /Threads_connected/{tc=$4}
    /Threads_running/{printf "%5d %5d %5d\n", q, tc, $4}'
2147483647   136     7
  798   136     7
  767   134     9
  828   134     7
  683   134     7
  784   135     7
  614   134     7
  108   134    24
  187   134    31
  179   134    28
 1179   134     7
 1151   134     7
 1240   135     7
 1000   135     7

Команда каждую секунду фиксирует выборку SHOW GLOBAL STATUS и передает данные в скрипт awk, который выводит количество запросов в секунду, Threads_ connected и Threads_running (количество запросов, выполняемых в данный мо­мент). Эта троица, как правило, очень чувствительна к остановкам сервера. Обыч­но в зависимости от характера проблемы и способа подключения приложения к MySQL число запросов в секунду уменьшается, а по крайней мере один из двух других показателей демонстрирует всплеск. В данном случае приложение, по- видимому, использует пул соединений, поэтому нет всплесков связанных потоков, но есть явная «кочка» в количестве выполняемых в этот момент запросов, при этом число запросов в секунду падает до доли от нормального уровня.

Как можно объяснить такое поведение? Рискованно строить догадки, но на прак­тике мы встречались с двумя распространенными случаями. Один из них является своего рода внутренним узким местом на сервере: новые запросы начинают выпол­няться, но накапливаются у какой-то блокировки, которую ждут старые запросы. Этот тип блокировки обычно оказывает давление на серверы приложений и при­водит к появлению там очередей. Другим распространенным случаем, который мы видели, является всплеск количества тяжелых запросов, например таких, которые могут появляться при неудачно настроенном устаревании memcached.

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

 

Команда SHOW PROCESSLIST

С помощью этого метода вы фиксируете выборки SHOW PROCESSLIST и ищете мно­жество потоков, которые находятся в необычных состояниях или имеют другие не­обычные характеристики. Например, довольно редко запросы остаются в состоянии «статистика» в течение длительного времени, поскольку это фаза оптимизации запросов, на которой сервер определяет лучший порядок соединения — обычно очень быстро.

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

Вертикальный вывод с помощью терминатора \G очень полезен для работы с SHOW PROCESS LIST, поскольку он помещает каждый столбец каждой строки вывода в собственную строку, что упрощает выполнение небольшого sort|uniq|sort- «заклинания», помогающего увидеть количество уникальных значений в любом желаемом столбце:

$ mysql -e 'SHOW PROCESSLIST\G' | grep State: | sort | uniq -c | sort -rn
    744   State:
     67   State: Sending data
     36   State: freeing items
      8   State: NULL
      6   State: end
      4   State: Updating
      4   State: cleaning up
      2   State: update
      1   State: Sorting result
      1   State: logging slow query

Если вы хотите изучить другой столбец, просто измените паттерн grep. Столбец State подходит для многих случаев. В данном примере мы видим огромное число потоков в состояниях, соответствующих окончанию запроса: «освобождение элемен­тов», «конец», «очистка» и «журналирование медленных запросов». Фактически во многих примерах на сервере, работа которого отражена в выведенной информации, наблюдалась такая же или подобная ситуация. Самым характерным и надежным индикатором проблемы было большое количество запросов в состоянии освобо­ждения элементов.

Вам не надо использовать методики командной строки для поиска подобных про­блем. Можете сделать запрос к таблице PROCESSLIST в INFORMATION_SCHEMA, если сервер довольно новый, или использовать утилиту innotop с большой частотой обновления и наблюдать на экране за необычным скоплением запросов. Только что рассмотренный пример был получен на сервере с проблемами внутреннего па­раллелизма и очистки InnoDB, но такая же ситуация может сложиться и в других обстоятельствах. Классическим примером было бы множество запросов в состоянии «заблокировано». Это неизменный отличительный признак MyISAM с ее блокиров­кой на уровне таблиц, быстро приводящей к захламлению сервера в случае большого количества записей в таблицах.

 

Использование журналирования запросов

Чтобы найти проблемы в журнале запросов, включите журнал медленных запро­сов, установите значение long_query_time, глобально равное 0, и убедитесь, что все соединения видят новый параметр. Возможно, вам придется перезапустить со­единения, чтобы они могли увидеть новое глобальное значение, или использовать функцию из пакета Percona Server, чтобы заставить изменения вступить в силу мгновенно, без прерывания существующих соединений.

Если по какой-либо причине вы не можете включить журнал медленных запросов для фиксации всех запросов, используйте для его эмуляции утилиты tcpdump и pt-query-digest. Ищите в журнале интервалы, на которых пропускная способ­ность внезапно падает. Запросы отправляются в журнал медленных запросов по мере завершения транзакции, поэтому захламление обычно приводит к внезап­ному падению количества завершенных транзакций, которое продолжается до тех пор, пока виновник не завершит работу и не освободит ресурс, блокирующий другие запросы. Затем будут завершены другие запросы. Что полезно в таком ха­рактерном поведении, так это то, что вы можете обвинить в захламлении первый запрос, который завершается после снижения пропускной способности. (Иногда это не самый первый запрос — часть запросов могут продолжать работать, пока другие заблокированы, поэтому такой подход не будет надежным в любой ситу­ации.)

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

$ awk '/^# Time:/{print $3, $4, c;c=0}/^# User/{c++}' slow-query.log
080913 21:52:17 51
080913 21:52:18 29
080913 21:52:19 34
080913 21:52:20 33
080913 21:52:21 38
080913 21:52:22 15
080913 21:52:23 47
080913 21:52:24 96
080913 21:52:25 6
080913 21:52:26 66
080913 21:52:27 37
080913 21:52:28 59

Как видите, здесь наблюдалось снижение пропускной способности, но, что интересно, ей предшествовал всплеск числа завершенных запросов. Не заглянув в журнал, труд­но сказать, что произошло, но, возможно, этот всплеск был связан с последующим падением. В любом случае ясно, что на сервере произошло что-то странное, и ис­следование журнала в области соответствующих временных меток может оказаться очень плодотворным. (Просмотрев этот журнал, мы обнаружили, что всплеск произо­шел из-за отключения соединений. Возможно, сервер приложений был перезапущен. Не все, что происходит, оказывается проблемой MySQL.)

 

Осмысление результатов

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

Для начала рекомендуем попробовать первые два подхода: SHOW STATUS и SHOW PROCESSLIST, потому что они малозатратны и могут быть выполнены в интерактивном режиме всего лишь со сценарием оболочки или повторным выполнением запросов. Анализировать журнал медленно работающих запросов гораздо труднее — при этом часто можно наблюдать какие-то странные закономерности, при более внимательном изучении пропадающие. Мы обнаружили, что легко представить себе закономерности там, где их нет.

Если вы обнаружите отклонение, что это будет означать? Обычно то, что запросы где-то в очереди или есть поток или всплеск определенного типа запросов. Дальней­шая задача состоит в том, чтобы обнаружить его причину.

 

Фиксация данных диагностики

При возникновении редко появляющейся проблемы важно измерить все, что возможно, и желательно во время ее проявления. Если вы сделаете это правильно, то соберете огромное количество данных диагностики. Сведения, которые вы не соби­раете, часто оказываются именно тем, что вам действительно нужно для правильного определения проблемы.

Для начала вам понадобятся две вещи.

  • Надежный и действующий в реальном времени триггер — способ узнать, когда возникает проблема.
  • Инструмент для сбора данных диагностики.

 

Диагностический триггер

Триггер очень важен для правильной работы. Это основа для фиксации данных при возникновении проблемы. Есть две основные вещи, мешающие триггеру работать правильно: ложноположительные и ложноотрицательные результаты. Если у вас есть ложноположительный результат, вы станете собирать данные диагностики, хотя ничего плохого не случилось. Тем самым будете напрасно тратить время и расстра­иваться. Из-за ложноотрицательных результатов вы упустите возможность найти проблему, потратите еще больше времени и серьезнее огорчитесь. Потратьте немного времени и убедитесь, что ваш триггер однозначно указывает на появление проблемы. Это будет не напрасным.

Что такое хороший критерий для триггера? Как показано в наших примерах, Threads_ running, как правило, очень чувствителен к проблемам, но довольно стабилен, когда все хорошо работает. Еще одним отличным показателем является всплеск необычных состояний потоков в SHOW PROCESSLIST. Помимо них, существует еще много способов наблюдать за этой проблемой, в том числе специальный вывод в SHOW INNODB STATUS, всплеск средней загрузки сервера и т. д. Ключевой момент состоит в получении чего-то, что можно сравнить с определенным порогом. Обычно это означает подсчет. Подойдет подсчет работающих потоков, подсчет потоков в состоянии освобождения элементов и т. п. При просмотре состояний потоков вам поможет параметр для grep:

$ mysql -e 'SHOW PROCESSLIST\G' | grep -c "State: freeing items"
36

Выберите такое пороговое значение, которое было бы достаточно высоким, чтобы его нельзя было достигнуть во время нормальной работы, но и не настолько высо­ким, чтобы нельзя было зафиксировать проблему, когда она появится. Остерегайтесь также устанавливать слишком высокое пороговое значение, поскольку в противном случае вы не обнаружите проблему сразу после ее появления. Обостряющиеся про­блемы, как правило, вызывают каскад других проблем, и если вы зафиксируете диа­гностическую информацию только после того, как все полетело в тартарары, вам, вероятно, будет труднее выявить исходную причину. Крайне желательно получить данные, когда вода просто стекает в раковину — до того, как громкий смыв оглушит вас Например, всплески в Threads_connected могут быть невероятно высокими — мы видели, как они увеличивались с 100 до 5000 и даже больше в течение пары минут. Вы могли бы использовать 4999 в качестве порогового значения, но зачем ждать, ког­да все станет настолько плохо? Если приложение, будучи работающим, не открывает более 150 соединений, начните сбор с 200 или 300.

Возвращаясь к примеру с Threads_running, отметим, что, похоже, нормальный уровень параллелизма — менее 10. Но 10 не будет хорошим пороговым значением — в этом случае существует большая вероятность ложноположительных результатов, и 15 недостаточно далеко, чтобы определенно быть вне нормального диапазона поведения. При 15 может произойти мини-захламление, но весьма вероятно, что красная линия не будет пересечена и проблема может рассосаться сама собой, прежде чем ситуация станет настолько критической, чтобы ее можно было четко диагностировать. В дан­ном примере мы бы предложили установить в качестве порогового значения 20.

По-видимому, вы хотели бы зафиксировать проблему, как только она появится, но только после небольшого ожидания, чтобы убедиться, что это не ложноположи­тельный результат или кратковременный всплеск. Итак, наш последний триггер такой: следите за статусом переменных с периодичностью один раз в секунду и, если Threads_running будет превышать показатель 20 в течение более 5 секунд, начните сбор диагностических данных. (Кстати, пример показал, что проблема исчезает через 3 секунды. Мы слегка подогнали его, чтобы сделать небольшим. Трехсекундную про­блему, как правило, трудно диагностировать. Однако большинство проблем, которые нам встречались, длятся немного дольше.)

Теперь следует настроить какой-то инструмент для просмотра сервера и реагиро­вания на срабатывания триггера. Вы могли бы написать его самостоятельно, но мы уже сделали это. В пакете Percona Toolkit есть инструмент pt-stalk, специально предназначенный для этих целей. У него много приятных функций, необходимость которых мы ощутили на собственной шкуре. Например, он следит за объемом свобод­ного места на диске, поэтому не заполнит диск собранными данными и не обрушит сервер. Вы же понимаете, что мы этого никогда не делали!

Инструмент pt-stalk очень прост в использовании. Вы можете установить параметры для просмотра, порогового значения, частоты проверок и т. п. У него намного больше замечательных возможностей, но для данного примера этого будет достаточно. Пре­жде чем применять его, прочтите руководство пользователя. Он опирается на другой инструмент для сбора данных, который мы обсудим далее.

 

Какие данные следует собирать

Теперь, когда вы определились с диагностическим триггером, можете использовать его для запуска процессов сбора данных. Но какие данные вы должны собирать? Ответ на этот вопрос уже звучал: все, что можете, но только за разумное время. Со­бирайте статистику операционной системы, данные об использовании процессора, диска и о свободном месте на нем, об использовании памяти, выборки вывода ps и все, что можете получить от MySQL, например выборки SHOW STATUS, SHOW PROCESSLIST и SHOW INNODB STATUS. Вся эта информация, а возможно, и еще какая-нибудь, вам по­надобится для диагностики проблемы.

Как вы помните, время выполнения делится на работу и ожидание. В общем случае есть два типа причин возникновения неизвестной проблемы. Сервер может выпол­нять много работы, потребляя много циклов процессора, или застрять в ожидании освобождения ресурсов. Необходимо применять два разных подхода, чтобы собрать диагностические данные для определения причин каждого из этих типов проблем. Вам нужен профиль, если система выполняет слишком много работы, и анализ ожи­даний, если она слишком долго ждет. Но как узнать, на чем следует сосредоточиться, если проблема неизвестна? Никак, поэтому лучше собрать данные для обоих типов проблем.

Первичным инструментом профилирования, который мы используем для внутренних серверов на GNU/Linux (в отличие от запросов по всему серверу), является oprofile. Примеры его применения будут показаны чуть позже. Можно также про­филировать системные вызовы сервера с помощью инструмента strace, но мы обнару­жили, что это рискованно для систем в рабочем состоянии. Об этом тоже поговорим позже. Для фиксации запросов в профиль мы предпочитаем использовать утилиту tcpdump. В большинстве версий MySQL журнал медленных запросов тяжело быстро включать и выключать, однако вы можете хорошо имитировать этот процесс с по­мощью трафика TCP. Кроме того, трафик полезен для многих других видов анализа.

Для анализа ожиданий мы обычно используем трассировки стека GDB. Потоки, застрявшие в одном месте внутри MySQL на протяжении длительного времени, как правило, имеют одну и ту же трассировку стека. Необходимо запустить gdb, прикре­пить его к процессу mysqld и сбрасывать трассировки стека для всех потоков. Затем вы можете использовать короткие скрипты для объединения общих трассировок стека и с помощью волшебных sort|uniq|sort показать, какие из них имеют больше всего общих черт. Чуть позже мы объясним, как использовать для этого инструмент pt-pmp.

Вы также можете анализировать ожидания с моментальными снимками, сделанными командами SHOW PROCESSLIST и SHOW INNODB STATUS, наблюдая за потоками и состояния­ми транзакций. Ни один из этих подходов не является абсолютно надежным, но на практике их применяют довольно часто, поскольку они весьма полезны.

Кажется, что сбор всех этих данных требует большой работы! Вероятно, вы уже этого ждете, но мы создали инструмент и для этих целей. Он называется pt-collect и также является частью пакета Percona Toolkit. Предназначен для выполнения совместно с pt-stalk. Чтобы собрать большинство важных данных, его следует запустить как root. По умолчанию он будет собирать данные в течение 30 с, а затем прекратит работу. Обычно этого бывает достаточно для диагностирования большин­ства проблем. В то же время это не так долго, чтобы получить ложнопозитивный результат.

Инструмент легко скачать, он не нуждается в какой-либо конфигурации — вся конфигурация переходит в pt-stalk. Убедитесь, что на вашем сервере установлены gdb и oprofile, и включите их в конфигурацию pt-stalk. Следует также убедиться, что mysqld содержит отладочные символы. Когда возникнет условие срабаты­вания триггера, инструмент соберет довольно полный набор данных. В опреде­ленном каталоге он создаст файлы с временными метками. На момент написания книги инструмент ориентирован скорее на GNU/Linux и нуждается в настройке на другие операционные системы, тем не менее его стоит использовать.

 

Интерпретация данных

Если вы правильно настроили условие триггера и позволили pt-stalk работать до­статочно долго для того, чтобы несколько раз обнаружить проблему, вы получите много данных для проверки. С чего следует начать? Во-первых, убедитесь, что про­блема действительно возникла, поскольку, имея множество выборок для проверки, вы вряд ли захотите тратить время на ложнопозитивные результаты. Во-вторых, посмотрите, не бросается ли в глаза что-то очевидное.

Очень полезно фиксировать, как выглядит сервер, когда все работает хорошо, а не только в случае неприятностей. Это помогает определить, является конкретный образец или даже часть образца ненормальным или нет. Например, когда вы просматриваете состояния запросов в списке процессов, можете ответить на вопрос: «Нормально ли, что многие запросы сортируют свои результаты?»

Полезнее всего обращать внимание на поведение запросов и транзакций, а также вну­треннее поведение сервера. Запрос и транзакция показывают, вызвана ли проблема тем, как используется сервер: плохо написанным SQL, плохим индексированием, плохим проектированием логической базы данных и т. д. Вы можете видеть, что пользователи делают с сервером, просматривая места, в которых появляются запро­сы и транзакции: журналированный трафик TCP, вывод команды SHOW PROCESSLIST и т. д. Внутреннее поведение сервера свидетельствует о том, есть ли на нем ошибки либо проблемы с производительностью или масштабируемостью. Вы можете обна­ружить ошибки в разных местах, а также в выводах oprofile и gdb. Но для интерпре­тации таких результатов требуется опыт.

Если вы не знаете, как интерпретировать полученную ошибку, то можете заархивиро­вать каталог с собранными данными и отправить его на анализ в службу поддержки. Любой компетентный специалист по поддержке MySQL сможет истолковать данные и объяснить вам, что они значат. Кроме того, он будет только рад, что вы отправили для ознакомления такие подробные данные. Возможно, вы также захотите отпра­вить вывод двух других инструментов пакета Percona Toolkit — pt-mysql-summary и pt-summary. Они показывают моментальные снимки статуса и конфигурации вашего экземпляра MySQL, операционной системы и оборудования соответственно.

Пакет Percona Toolkit включает в себя инструмент, который поможет вам быстро просмотреть множество выборок собранных данных. Он называется pt-sift, помогает перемещаться между выборками, показывает сводку каждой выборки и позволяет при необходимости погрузиться в отдельные биты данных. Этот инструмент может сэкономить много времени.

Ранее мы приводили примеры счетчиков статуса и состояний потоков. В заключение этой главы покажем несколько примеров вывода инструментов oprofile и gdb. Вот вы­данный oprofile отчет с сервера, на котором возникла проблема. Вы можете ее найти?

samples  %        image name   app name     symbol  name
893793   31.1273  /no-vmlinux  /no-vmlinux  (no symbols)
325733   11.3440  mysqld       mysqld       Query_cache::free_memory_block()
117732    4.1001  libc         libc         (no symbols)
102349    3.5644  mysqld       mysqld       my_hash_sort_bin
 76977    2.6808  mysqld       mysqld       MYSQLparse()
 71599    2.4935  libpthread   libpthread   pthread_mutex_trylock
 52203    1.8180  mysqld       mysqld       read_view_open_now
 46516    1.6200  mysqld       mysqld       Query_cache::invalidate_query_block_list()
 42153    1.4680  mysqld       mysqld       Query_cache::write_result_data()
 37359    1.3011  mysqld       mysqld       MYSQLlex()
 35917    1.2508  libpthread   libpthread   __pthread_mutex_unlock_usercnt
 34248    1.1927  mysqld       mysqld       __intel_new_memcpy

Если вы ответили «кэш запросов», вы правы. Кэш запросов этого сервера порождал слишком много работы и все тормозил. Замедление в 50 раз произошло мгновенно, без каких-либо других изменений в системе. Отключение кэша запросов нормали­зовало работу сервера. В этом примере интерпретировать внутреннюю среду сервера оказалось довольно просто.

Другим важным инструментом анализа узких мест является рассмотрение ожиданий с трассировкой стека с помощью gdb. Трассировка стека одного потока обычно вы­глядит следующим образом (мы немного отформатировали ее для печати):

Thread 992 (Thread 0x7f6ee0111910 (LWP 31510)):
#0  0x0000003be560b2f9 in pthread_cond_wait@@GLIBC_2.3.2 () from /libpthread.so.0
#1  0x00007f6ee14f0965 in os_event_wait_low () at os/os0sync.c:396
#2  0x00007f6ee1531507 in srv_conc_enter_innodb () at srv/srv0srv.c:1185
#3  0x00007f6ee14c906a in innodb_srv_conc_enter_innodb () at handler/ha_innodb.cc:609
#4  ha_innodb::index_read () at handler/ha_innodb.cc:5057
#5  0x00000000006538c5 in ?? ()
#6  0x0000000000658029 in sub_select() ()
#7  0x0000000000658e25 in ?? ()
#8  0x00000000006677c0 in JOIN::exec() ()
#9  0x000000000066944a in mysql_select() ()
#10 0x0000000000669ea4 in handle_select() ()
#11 0x00000000005ff89a in ?? ()
#12 0x0000000000601c5e in mysql_execute_command() ()
#13 0x000000000060701c in mysql_parse() ()
#14 0x000000000060829a in dispatch_command() ()
#15 0x0000000000608b8a in do_command(THD*) ()
#16 0x00000000005fbd1d in handle_one_connection ()
#17 0x0000003be560686a in start_thread () from /lib64/libpthread.so.0
#18 0x0000003be4ede3bd in clone () from /lib64/libc.so.6
#19 0x0000000000000000 in ?? ()

Стек читают снизу вверх, то есть в настоящее время выполняется поток внутри функции pthread_cond_wait, которая была вызвана из os_event_wait_low.

Считывая трассировку дальше, мы видим, что, судя по всему, этот поток пытался войти в ядро InnoDB (srv_conc_enter_innodb), но попал во внутреннюю очередь (os_event_wait_low), потому что в ядре уже было больше потоков, чем указано в пере­менной innodb_thread_concurrency. Однако реальное значение трассировки стека объ­единяет их. Это методика, которую Домас Митузас (Domas Mituzas), бывший инженер поддержки MySQL, сделал популярной благодаря инструменту «профилировщик для бедных». В настоящее время он работает в Facebook и вместе с коллегами разработал множество инструментов для сбора и анализа трассировок стека. Вы можете больше узнать о существующих инструментах на сайте http://www.poomiansprofiler.org.

В пакете Percona Toolkit есть наша реализация «профилировщика для бедных» под названием pt-pmp. Это оболочка и программа awk, которая объединяет аналогичные трассировки стека и выполняет обычные команды sort|uniq|sort, показывая первыми наиболее часто встречающиеся. Далее показано, как выглядит полный набор трасси­ровок стека. Мы будем использовать параметр -15 для отсечения трассировки стека после пяти уровней так, чтобы не было большого количества трассировок с общими вершинами, но с разными основаниями, что могло бы помешать объединить их и увидеть, где на самом деле наблюдаются ожидания:

Первая строка является характерной сигнатурой простаивающего потока в MySQL, поэтому можете ее проигнорировать. Наиболее интересна вторая строка: она по­казывает, что множество потоков ожидают входа в ядро InnoDB, но блокируются. Третья строка показывает множество потоков, ожидающих некоторого мьютекса, но какого именно, мы увидеть не можем, поскольку отсекли более глубокие уровни трассировки стека. Если важно узнать, какой это мьютекс, следует перезапустить инструмент с большим значением параметра -l. В целом трассировки стека по­казывают, что множество потоков ждут своей очереди внутри InnoDB. Но почему так происходит? Это непонятно. Чтобы ответить на этот вопрос, нам, по-видимому, нужно поискать в другом месте.

Как видно из отчетов по трассировке стека и отчетов oprofile, такой вид анализа не всегда подходит для тех, кто не разбирается в исходном коде MySQL и InnoDB. В этом случае придется кого-то звать на помощь.

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

 

Вас заинтересует / Intresting for you:

Модель развития базы данных My...
Модель развития базы данных My... 1416 просмотров Ирина Светлова Thu, 10 Jan 2019, 12:29:03
Обзор версий MySQL - какой рел...
Обзор версий MySQL - какой рел... 10611 просмотров Ирина Светлова Fri, 05 Feb 2021, 17:19:41
Выбор оптимальных типов данных...
Выбор оптимальных типов данных... 9760 просмотров Валерий Павлюков Sun, 27 Oct 2019, 15:24:19
Транзакции в базе данных MySQL
Транзакции в базе данных MySQL 21499 просмотров Ирина Светлова Mon, 07 Jan 2019, 05:18:23
Войдите чтобы комментировать

AidaU аватар
AidaU ответил в теме #9368 5 года 1 мес. назад

iVoron пишет: Классная инструкция! С нетерпением ждем публикации обещанного Кейса по диагностики MySQL!

Кейс готов. Ссылка в конце блога!)
iVoron аватар
iVoron ответил в теме #9365 5 года 1 мес. назад
Классная инструкция! С нетерпением ждем публикации обещанного Кейса по диагностики MySQL!