Справочное руководство по MySQL

         

Примечания к Linux (Все версии Linux)

Приведенные ниже замечания о glibc будут полезны только для случая, когда вы собираете MySQL самостоятельно. Но обычно, если Linux работает на машине с архитектурой x86, гораздо лучше использовать наши бинарные файлы. Они линкуются с glibc, к которой применены наиболее удачные патчи, и с наиболее удачными опциями компилятора - все это сделано для того, чтобы программа была пригодной для работы на сильно нагруженном сервере. Поэтому если после прочтения данного раздела у вас возникнут сомнения относительно дальнейших действий, попробуйте сначала использовать бинарные файлы - возможно, они удовлетворят вашим требованиям. Если же окажется, что бинарные файлы вас не устраивают, то можно попробовать заняться собственноручной сборкой. Мы будем очень признательны за сообщение о том, почему вам пришлось отказаться от работы с нашими бинарниками, - это поможет нам в следующий раз собрать более удачную версию программы. Что же касается обычных пользователей, то для них даже при установке, рассчитанной на большое количество параллельных соединений и/или таблиц, превосходящих по объему ограничение в 2 Гб, наши бинарные файлы будут


наилучшим вариантом выбора.

В операционной системе Linux MySQL использует LinuxThreads. Если у вас старая система Linux, в которой отсутствует glibc2, то прежде чем предпринимать попытку компиляции MySQL, необходимо установить LinuxThreads. Получить LinuxThreads можно по адресу http://www.mysql.com/downloads/os-linux.html.

Примечание: на Linux 2.2.14 и MySQL, установленных на многопроцессорных (SMP) системах, могут возникать некоторые непонятные проблемы. В таком случае мы рекомендуем как можно быстрее сделать апгрейд версии ядра до 2.4: оно станет гораздо более быстрым и устойчивым.

Необходимо отметить, что версии glibc до 2.1.1 включительно содержат фатальную ошибку в обработке pthread_mutex_timedwait, которая проявляется при использовании INSERT DELAYED. Поэтому мы рекомендуем не использовать INSERT DELAYED, пока не будет сделан апгрейд glibc.

Если планируется использовать более 1000 одновременных соединений, необходимо сделать некоторые изменения в LinuxThreads, пересобрать их и перелинковать MySQL с новой `libpthread.a'. Следует увеличить PTHREAD_THREADS_MAX в файле `sysdeps/unix/sysv/linux/bits/local_lim.h' до 4096 и уменьшить STACK_SIZE в `linuxthreads/internals.h' до 256 Kб.

Пути указаны относительно корневого каталога glibc. Заметим, что MySQL не будет устойчиво работать при 600-1000 соединениях, если размер STACK_SIZE останется по умолчанию 2 Mб.

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

В Linux 2.2 и более свежих версиях можно получить значение максимального количества файлов, которые можно открыть одновременно. Для этого необходимо выполнить:

cat /proc/sys/fs/file-max
cat /proc/sys/fs/dquot-max
cat /proc/sys/fs/super-max

В случае, если на машине установлено более 16 Mб памяти, к загрузочному скрипту (`/etc/init.d/boot.local' на SuSE) необходимо добавить записи наподобие следующих:

echo 65536 > /proc/sys/fs/file-max
echo 8192 > /proc/sys/fs/dquot-max
echo 1024 > /proc/sys/fs/super-max

Эти команды можно также запустить из командной строки от имени пользователя

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

Альтернативно, вы можете установить эти параметры при загрузке, используя утилиту sysctl, которая используется во множестве поставок Linux (SuSE также добавила ее, начиная с SuSE 8.0). Просто напишите такие значения в файл `/etc/sysctl.conf':

# увеличить некоторые значения для MySQL
fs.file-max = 65536
fs.dquot-max = 8192
fs.super-max = 1024

Кроме того, необходимо добавить в `/etc/my.cnf':

[safe_mysqld]
open-files-limit=8192

Добавление такой записи позволит MySQL создавать до 8192 соединений и файлов.

Размером стеков потоков в адресном пространстве управляет константа STACK_SIZE в LinuxThreads. Ее значение должно быть достаточно большим, чтобы хватило места стеку каждого потока, но достаточно малым, чтобы предотвратить попадание стеков некоторых потоков в область общих данных mysqld. К сожалению, опытным путем нам удалось обнаружить, что реализация mmap() на Linux в случае поступления запроса на выделение адреса, который уже используется, вместо возвращения сообщения об ошибке успешно освобождает все ранее выделенные области и обнуляет данные на всей странице. Поэтому безопасность использования mysqld или любого другого потокового приложения зависит от "джентльменского" поведения кода, создающего потоки. Пользователь должен принять меры для обеспечения достаточно малого количества выполняемых потоков в любой момент времени, чтобы стеки потоков не пересекались с динамически выделяемой памятью. В случае mysqld необходимо навязать это "джентльменское" поведение установкой переменной max_connection в разумных пределах.

Если вы собираете MySQL самостоятельно и не хотите заниматься патчами LinuxThreads, то необходимо установить значение max_connections так, чтобы оно не превышало 500. Это значение должно быть еще меньше, если у вас достаточно велик буфер ключей, большая таблица динамически выделяемой памяти или имеются другие причины, по которым mysqld занимает большие объемы памяти, а также в случае, если вы используете ядро 2.2 с патчами для 2 Гб. Если используются наши бинарные файлы или RPM версии не старше 3.23.25, то можно безопасно устанавливать max_connections равным 1500 - при условии, что буфер ключей или таблицы динамически выделяемой памяти имеют небольшие размеры. Чем меньше STACK_SIZE в LinuxThreads, тем больше потоков можно безопасно создать. Рекомендуемая нами величина составляет от 128K до 256K.

При использовании множества одновременных соединений вы можете пострадать от одной "особенности" ядра 2.2. Данная особенность заключается в том, что процесс штрафуется за ветвление или порождение дочерних процессов - чтобы предотвратить атаки ветвлением. Это приводит к неудачному масштабированию MySQL при увеличении количества одновременных соединений. По нашим данным, на однопроцессорных машинах из-за данной особенности создание потоков происходит очень медленно, что может привести к большим затратам времени на соединение с MySQL (до 1 минуты), и столько же может занять завершение соединения. Что же касается многопроцессорных систем, то на них наблюдалось постепенное снижение скорости по мере роста числа клиентов. Пока мы пытались найти решение проблемы, один из пользователей прислал патч к ядру, утверждая, что патч заметно улучшил работу его сайта. Патч доступен по адресу http://www.mysql.com/Downloads/Patches/linux-fork.patch. Мы провели достаточно обширное тестирование этого патча как на развивающейся, так и на промышленной версиях системы. Применение патча заметно улучшило производительность MySQL, не вызвав при этом никаких проблем, поэтому теперь мы рекомендуем его пользователям, которые до сих пор используют ядро 2.2 на сильно нагруженных серверах. Кроме того, эта проблема была решена в ядре 2.4, поэтому если вас не устраивает производительность системы, то, по-видимому, проще сделать ее апгрейд до 2.4, чем использовать патчи к ядру 2.2. При обновлении системы, помимо исправления этой ошибки, вы также получите возможность воспользоваться преимуществами SMP.

При тестировании MySQL на двухпроцессорной машине с ядром 2.4 мы обнаружили, что MySQL масштабируется гораздо лучше - фактически отсутствовало замедление обработки запросов вплоть до 1000 соединений, а фактор масштабируемости MySQL (который вычисляется как отношение максимальной производительности к производительности при работе с одним клиентом) достигал 180%. Подобные результаты мы наблюдали на четырехпроцессорной системе - фактическое отсутствие замедления при росте количества соединений до 1000 при факторе масштабируемости в 300%. Поэтому для интенсивно нагруженных серверов мы настоятельно рекомендуем ядро 2.4. Оказалось также, что для достижения максимума производительности на ядре 2.4 весьма важно запускать mysqld с наибольшим возможным приоритетом. Для этого следует добавить в скрипт safe_mysqld команду renice -20 $$. В наших тестах на четырехпроцессорной машине увеличение приоритета привело к повышению производительности на 60% при работе 400 клиентов.

В дополнение к этому мы сейчас занимаемся сбором информации о производительности MySQL с ядром 2.4 на четырех- и восьмипроцессорных системах. Если у вас есть доступ к таким системам и вы тестировали их производительность, пожалуйста, отправьте сообщение с результатами по адресу docs@mysql.com - мы добавим эти результаты в документацию.

Существует еще один нюанс, заметно влияющий на производительность

MySQL, особенно на многопроцессорных системах. В LinuxThreads в glibc-2.1 очень плохо реализованы mutex'ы для программ со множеством потоков, в которых mutex хранится непродолжительное время. Парадоксально, но факт: в случае, если на многопроцессорных системах собрать MySQL с немодифицированными LinuxThreads, то при удалении процессора во много раз увеличивается производительность. Для решения этой проблемы мы предлагаем патч к glibc 2.1.3 (http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch).

В glibc-2.2.2 MySQL версии 3.23.36 использует адаптивный mutex, который гораздо лучше даже ``патченного'' в glibc-2.3.1. Однако предупреждаем, что при некоторых условиях код mutex'а в glibc-2.2.2 "закручивается" (overspin), а это ухудшает производительность MySQL. Шансы возникновения такого события можно понизить, если повысить приоритет выполнения mysqld. Можно также исправить "закручивание" с помощью патча, доступного по адресу http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch. Он содержит в себе коррекцию "закручивания", максимальное количество потоков и размеры стека - все вместе. Необходимо применить его в каталоге linuxthreads командой patch -p0 </tmp/linuxthreads-2.2.2.patch. Мы надеемся, что данный патч будет в некотором виде включен в следующие выпуски glibc-2.2. В любом случае - если вы линкуете с использованием библиотеки glibc-2.2.2, то пока что необходимо исправлять STACK_SIZE и PTHREAD_THREADS_MAX. Мы не теряем надежду, что в будущем значения по умолчанию будут приведены к более приемлемым для сборки интенсивно нагруженного MySQL величинам, так что самостоятельная сборка сведется к выполнению ./configure; make; make install.

Вышеупомянутые патчи мы рекомендуем использовать только для создания специальной статической версии `libpthread.a', а последнюю - применять только для статического линкования MySQL. Мы уверены, что для MySQL эти патчи безопасны и заметно улучшают его производительность, но относительно других приложений данных нет. Линкуя другие приложения с ``патченной'' версией библиотеки или собирая ее динамическую версию и устанавливая ее на свою систему, вы осознанно идете на риск по отношению к другим приложениям, использующим LinuxThreads.

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

Существует одна известная проблема с бинарным дистрибутивом, касающаяся старых систем Linux, в которых используется libc (таких как RedHat 4.x или Slackware). Она проявляется в виде некоторых некритичных проблем с разрешением имен (see section 2.6.1.1 Примечания к бинарным дистрибутивам Linux).

При использовании LinuxThreads одновременно работают как минимум три процесса. По сути это потоки. Один поток управляет LinuxThreads, один - обрабатывает соединения и еще один - обрабатывает различные сигналы.

Заметим, что ядро Linux и библиотека LinuxThreads по умолчанию могут поддерживать только 1024 потока. Это значит, что может существовать не более 1021 соединения с MySQL на системе, к которой не применялись патчи. Информацию о том, как обойти это ограничение, можно найти на странице http://www.volano.com/linuxnotes.html.

Если по результату работы команды ps вы видите, что mysqld прекратил работу,

то обычно причиной этого является либо обнаружение ошибки в MySQL, либо испорченная таблица (see section A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями).

Если при получении сигнала SIGSEGV mysqld просто умирает, то для получения образа памяти (core dump) на Linux можно запустить mysqld с опцией --core-file. Заметим, что при этом вам, возможно, придется увеличить размер допустимого объема файла образа памяти путем добавления строки ulimit -c 1000000 в safe_mysqld или запуском safe_mysqld с опцией --core-file-size=1000000 (see section 4.7.2 safe_mysqld, оболочка mysqld).

Если при линковании собственного MySQL-клиента возникла ошибка:

ld.so.1: ./my: fatal: libmysqlclient.so.4:
open failed: No such file or directory

то проблему можно обойти одним из следующих способов:

  • линковать клиент с одним из флагов: -Wl,r/path-libmysqlclient.so. (вместо -Lpath);
  • скопировать `libmysqclient.so' в `/usr/lib';
  • добавить путь к каталогу, в котором находится `libmysqlclient.so', к переменной окружения LD_RUN_PATH перед запуском клиента.

Если вы используете компилятор Fujitsu (fcc / FCC), то возможны некоторые проблемы компиляции MySQL поскольку заголовки в Linux в значительной степени ориентированы на gcc.

Данная конфигурация должна работать с fcc/FCC:

CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \
-DCONST=const -DNO_STRTOLL_PROTO" CXX=FCC CXXFLAGS="-O -K fast -K lib \
-K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE -DCONST=const \
-Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \
'-D_EXTERN_INLINE=static __inline'" ./configure --prefix=/usr/local/mysql\
--enable-assembler --with-mysqld-ldflags=-all-static --disable-shared \
--with-low-memory
Содержание раздела