Тюнинг тредов в Mysql (mysql threads tunning)

mysqld это «один процесс — много тредов». В достаточно приближенном понимании тред (thread) это когда процесс копирует сам себя, и родительский процесс передает треду какую то задачу для решения.
Создание треда отличается от обычного fork() в основном тем, что fork порождает +1 процесс, тогда как деление на треды использует другую, более производительную технологию ветвления без клонирования данных в памяти.

При каждом подключении клиента, mysql создает тред, который это подключение обрабатывает.

Если у вас средне нагруженый mysqld, то убедитесь что mysqld работает на нормальной реализации тредов. К примеру, FreeBSD ниже 6 ветки имеет ненормальную, глючную реализацию тредов pthread. Основные глюки проявляются при работе на SMP (более 1 процессора). pthread «не умеет» нормально раскидывать треды по разным процессорам и в результате мы имеем ситуацию, когда Mysqld висит только на одном процессоре вместе с кучей своих детишек. Все остальные процессоры курят, даже если мускуль съел все процессорное время своего процессора.

Более детальная информация как правильно заставить работать mysql под FreeBSD может быть найдена тут: http://dev.mysql.com/doc/refman/5.1/en/freebsd.html

Итак, посмотрим что у вас творится с тредами. Если сервер слабо нагружен и имеет 1-2 подключения одновременно, то в этой оптимизации особого смысла нет. Гораздо ощутим результат, когда сервер серъезно нагружен и имеет много конкурентных запросов.

Посмотрим статус

shell> mysqladmin extended-status

Обратим внимание на значения:

Threads_cached
Threads_connected
Threads_created
Threads_running

Если Threads_cached равно нулю, у вас отключен кеш тредов. Т.е. при каждом подключении создается новый тред, а при отключении он уходит в /dev/null ;). Это плохо. Когда включен кеш тредов, то при отключении клиента тред уходит в кеш, а при новом подключении он не создается, а берется из кеша. Это гигантская экономия ресурсов при больших нагрузках. В некоторых ситуациях нагрузка уменьшалась в разы при использовании thread cache.

Threads_cached — количество тредов в кеше

Threads_connected — грубо говоря, количество открытых подключений

Threads_running — Сколько тредов сейчас «работают»

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

Что делать если Threads_created имеет слишком высокое значение?

В my.cnf есть такой параметр thread_cache_size (или просто thread_cache). Его необходимо увеличивать эксперементальным путем до той поры пока Threads_created не примет порядок цифр Threads_cached.

Для определения начального значения, вам надо узнать, сколько тредов бывает в среднем запущено в пиковых нагрузках. Для мониторинга сгодится утилитка mytop (она может не работать если mysql скомпилирован статически).

Либо периодически запускать такую команду:

shell> echo "SHOW GLOBAL STATUS" | mysql | grep Threads_connected | awk '{print $2;}'

Определили среднее значение, записали в my.cnf (thread_cache), сделали рестарт сервера. Пошли, покурили, выпили чайку. Смотри статус (команда указана выше). Если Threads_created продолжает неугомонно расти выше значения кеша, увеличиваем переменную thread_cache. И так до победы, но не советую растить эту величину выше нескольких сотен — рискуете получить Out Of Memory.

При увеличении этой величины также надо мониторить Resident Set Size процесса mysqld в долгосрочной динамике. Это колонка RSS в утилите «top». Означает сколько mysql сейчас занимает места в оперативе. Не советую растить его выше половины объема вашей оперативной памяти, т.к. получите пенальти, когда начнут ужиматься системные кеши.

Нормальное значение thread_cache, при котором Threads_created держится на приемлимом уровне, а mysql умеренно жрет память колеблется от 5 до 100 в зависимости от нагрузки и величины доступного ОЗУ.

Слишком высокое значение thread_cache может необоснованно кушать лишнюю память.

Если вас это не спасло, thread_cache превышает мыслимые нормы и Mysql продолжает жрать память и процессор и порождать треды, то необходима комплексная оптимизация: 1. системы, 2. ядра, 3. логики скриптов и запросов 4. других стартовых параметров mysqld