Можно ли заставить MySQL использовать более одного ядра?

131

Мне представили несколько выделенных серверов MySQL, которые никогда не используют более одного ядра. Я больше разработчик, чем администратор баз данных для MySQL, поэтому нужна помощь

Настроить

Серверы довольно здоровенные с нагрузкой типа OLAP / DataWarehouse (DW):

  • Основной: 96 ГБ ОЗУ, 8 ядер + один массив RAID 10
  • Тест: 32 ГБ ОЗУ с 4 ядрами
  • Самая большая БД составляет 540 ГБ, общий объем около 1,1 ТБ и в основном таблицы InnoDB.
  • Солярис 10 Intel-64
  • MySQL 5.5.x

Примечание. Самая большая БД является реплицированной с сервера OLTP DR, и с нее загружается DW. Это не полный DW: только последние 6 месяцев до 6 недель, поэтому он меньше, чем OLTP DB.

Наблюдения на тестовом сервере

  • 3 отдельных соединения
  • у каждого есть одновременно (и разные) ALTER TABLE...DROP KEY...ADD INDEX
  • 3 таблицы имеют 2,5, 3,8 и 4,5 миллиона строк
  • Загрузка процессора увеличивается до 25% (одно ядро ​​максимально) и не выше
  • 3 АЛЬТЕРЫ занимают 12-25 минут (сингл на наименьшем занимает 4,5)

Вопросов

  1. Какие настройки или патчи требуются для использования более одного ядра?
    То есть, почему MySQL не использует все доступные ядра? (как и другие РСУБД)
  2. Это следствие репликации?

Другие заметки

  • Я понимаю разницу между «потоком» СУБД и «потоком» ОС
  • Я не спрашиваю о какой-либо форме параллелизма
  • Некоторые системные переменные для InnoDB и потоков являются неоптимальными
    (в поисках быстрого выигрыша)
  • В краткосрочной перспективе я не могу изменить расположение дисков
  • ОС можно настроить при необходимости
  • Один ALTER TABLE на самом маленьком столе занимает 4,5 минуты (шокирующая IMO)

Редактировать 1

  • Значение innodb_thread_concurrency равно 8 для обоих. Да, это неправильно, но MySQL не будет использовать несколько ядер
  • Размер innodb_buffer_pool_size составляет 80 ГБ на основном сервере, 10 ГБ на тесте (другой экземпляр отключен). Это нормально на данный момент.
  • innodb_file_per_table = ON

Редактировать 2

  • innodb_flush_log_at_trx_commit = 2
  • innodb_use_sys_malloc = ON
  • innodb_flush_method должен быть O_DIRECT (но SHOW VARIABLES не показывает это)
  • innodb_doublewrite = OFF
  • Файловая система = ZFS (и мой системный администратор нашел это: http://blogs.oracle.com/realneel/entry/mysql_innodb_zfs_best_practices )

Тестировать

  • innodb_flush_method не отображается как O_DIRECT, когда это должно быть
  • будет следовать настройкам RolandoMySQLDBA

Дайте мне знать, если я пропустил что-то важное

ура

Обновить

Изменено innodb_flush_method + 3 настройки потока в ответе RolandoMySQLDBA.
Результат:> 1 ядро, использованное для тестов = положительный результат

ГБН
источник
@Dtest: innodb_file_per_table = ON. ПОКАЗАТЬ СТАТУС ДВИГАТЕЛЯ INNODB \ G только для командной строки?
ГБН
@Dtest: я не получил вывод в SQLyog и должен был бы попросить кого-то запустить это из командной строки
gbn
1
webyog.com/forums/index.php?showtopic=1290 должен работать без \G. Кроме того, я думаю, что SHOW INNODB STATUSне рекомендуется в пользу SHOW ENGINE INNODB STATUSверсии 5.5 (я получаю сообщение об ошибке при запуске первого в командной строке.
Дерек Дауни,
1
Хотя все остальные ответы хороши, так как вы являетесь разработчиком, я бы рекомендовал взглянуть на Shard Query code.google.com/p/shard-query. Это может помочь вам, особенно в среде хранилища данных.
Джонатан
Спасибо, это один из вариантов, о котором мы подумали. Я также беру на себя роль DBA.
ГБН

Ответы:

123

На самом деле я обсуждал innodb_thread_concurrency с экспертом MySQL на конференции Percona Live NYC в мае 2011 года .

Я узнал кое-что удивительное: несмотря на документацию, лучше оставить innodb_thread_concurrencyв 0 (бесконечный параллелизм). Таким образом, InnoDB решает, какое лучшее число innodb_concurrency_ticketsоткрыть для заданной установки экземпляра MySQL.

Как только вы установите innodb_thread_concurrency0, вы можете установить innodb_read_io_threadsи innodb_write_io_threads(оба начиная с MySQL 5.1.38) максимальное значение 64. Это должно задействовать больше ядер.

RolandoMySQLDBA
источник
Попробую это. Я собирался установить innodb_thread_concurrency на 0 в любом случае, основываясь на материалах, которые я тоже читал
gbn
9
+1 для innodb_thread_concurrency = 0
рандом x
3
@gbn - Признание от # 1 парня из DBA.SE, спасибо, это повышение уверенности и очень ценится. Спасибо и добро пожаловать !!!
RolandoMySQLDBA
set global innodb_read_io_threads = 8 Код ошибки: 1238. Переменная 'innodb_read_io_threads' является переменной только для чтения
wgq3g23g
2
@ wgq3g23g Если вы выполняете RDS, измените его в группе параметров БД и перезагрузите экземпляр. Если вы используете EC2 или голый металл, добавьте эту опцию my.cnfи перезапустите mysqld. Пожалуйста.
RolandoMySQLDBA
29

MySQL будет автоматически использовать несколько ядер, поэтому либо ваша загрузка в 25% является совпадением 1, либо возможна неправильная конфигурация в Solaris. Я не буду притворяться, что знаю, как настроить солярис, но вот статья, в которой приводится некоторая информация о настройке соляриса .

Страницы настройки InnoDB были пересмотрены в MySQL 5.5, так что там также есть некоторая полезная информация. Из советов по вводу / выводу диска InnoDB :

Если верхний инструмент Unix или диспетчер задач Windows показывает, что процент использования ЦП с вашей рабочей нагрузкой составляет менее 70%, ваша рабочая нагрузка, вероятно, связана с диском. Возможно, вы делаете слишком много транзакций, или буферный пул слишком мал. Увеличение буферного пула может помочь, но не устанавливайте его равным более 80% физической памяти.

Некоторые другие вещи, чтобы проверить:

  • Переключение innodb_flush_method на O_DIRECT стоит протестировать. Если это поможет, вам может понадобиться смонтировать файловую систему с forcedirectioопцией

  • Измените innodb_flush_log_at_trx_commit с 1 на 0 (если вы не против потерять последнюю секунду при сбое mysql) или 2 (если вы не против потерять последнюю секунду при сбое ОС).

  • Проверьте значение innodb_use_sys_malloc . Эта статья имеет больше информации о переменной.

    В то время не было библиотек распределения памяти, настроенных для многоядерных процессоров. Поэтому InnoDB реализовал свой собственный распределитель памяти в подсистеме mem. Этот распределитель защищен одним мьютексом, который может стать узким местом.

    Но есть некоторые предостережения в конце раздела о том, что означает включение переменной (она включена по умолчанию в 5.5).

    Обратите внимание, что когда распределитель памяти InnoDB отключен, InnoDB будет игнорировать значение параметра innodb_additional_mem_pool_size.

  • Вполне возможно, что репликация вызывает некоторые проблемы. Я понимаю, что вы не заинтересованы в параллелизме, но из описания этого рабочего журнала :

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

В конечном счете, InnoDB может оказаться не лучшим механизмом для хранилищ данных из-за происходящих операций на диске. Вы могли бы рассмотреть возможность изменения таблиц хранилища данных для Compressed MyISAM .

1 По стечению обстоятельств я имею в виду узкое место, которое не позволяет вашей нагрузке возрастать выше 25%, но не обязательно является вынужденной проблемой с одним ядром.

Дерек Дауни
источник
Благодарю. Раздел настроек добавлен в вопрос. Проблема заключается в нескольких интенсивных запросах, использующих одно ядро: пока что нет настроек памяти или потоков. Больше потоков все еще работает на том же ядре
gbn
@gbn спасибо за обновление, все еще смотрю. Я думал, что это было «совпадение». Мне интересно, если это проблема только соляриса ( developers.sun.com/solaris/articles/mysql_perf_tune.html ), но я не знаю много об этой системе.
Дерек Дауни,
1
@Dtest: Я тоже отправлю эту статью администратору Solaris. Там есть кое-что хорошее
gbn
1
Теперь репликация (опционально) многопоточная на подчиненном устройстве. InnoDB улучшилось с тех пор, как этот ответ был написан. Я бы не советовал использовать MyISAM, особенно если он не сжат.
Рик Джеймс
15

Одно соединение будет использовать только одно ядро. (Хорошо, InnoDB использует другие потоки, а значит и ядра, для некоторой обработки ввода-вывода, но это не важно.)

У вас было 3 ALTER, поэтому вы не использовали намного больше, чем 3 ядра.

Увы, даже PARTITION не использует несколько ядер.

До недавнего времени несколько соединений были максимально до 4-8 ядер. Xtradb в Percona (входит в MariaDB) лучше использует несколько ядер, но по-прежнему только по одному на поток. Они максимально на 32 ядра.

Рик Джеймс
источник
(Обновление в 2015 году :) Несколько соединений с максимумом 5,6 при 48 ядрах. 5.7 обещает быть еще лучше. (Так говорит Oracle, эталонные тесты.) Но по-прежнему не нужно использовать несколько ядер для одного соединения.
Рик Джеймс
Обновление (после перехода на Oracle OpenWorld): новая версия 8.x не будет иметь никакого параллелизма.
Рик Джеймс
9

ИМХО и в описанном сценарии использования вы никогда не будете использовать более одного ядра. Причина в том, что ваша рабочая нагрузка связана с вводом-выводом, а не с процессором. Поскольку ваши 3 соединения создают новый индекс, каждому из них необходимо прочитать всю таблицу с диска: это то, что требует времени, а не вычисления индексов.

jfg956
источник
8

Учтите, что вашим узким местом может быть производительность ввода-вывода вашей файловой системы.

В дополнение к настройкам, предложенным @RolandoMySQLDBA , я также установил noatimeпараметры монтирования /etc/fstabдля раздела, содержащего мой каталог данных mysql ( /data01/mysqlв моем случае, с /dev/sdb1подключенным к /data01).

По умолчанию linux записывает время доступа для КАЖДОГО чтения или записи диска, что отрицательно влияет на производительность ввода-вывода, особенно для приложений с высоким вводом-выводом, таких как базы данных. Это означает, что даже чтение данных из файла запускает запись на диск ... WAT!

Чтобы отключить это, добавьте noatimeопцию монтирования в /etc/fstabдля желаемой точки монтирования следующим образом (пример в моем случае):

/dev/sdb1  /data01  ext4  defaults,noatime  0  2

Затем перемонтируйте раздел:

mount -o,remount /data01

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

OkezieE
источник