|
Приложение E. Перенос на другие системы
Цель данного раздела - обеспечить
помощь в переносе MySQL на другие
операционные системы. Но сначала
необходимо ознакомиться со списком
поддерживаемых в настоящее время
операционных систем (see
Раздел 2.2.3, «Операционные системы, поддерживаемые
MySQL»). Если вы создали новую
версию переноса MySQL, пожалуйста,
сообщите нам - тогда мы включим ее в
настоящий список и в список на нашем
веб-сайте (http://www.mysql.com/) и сможем
рекомендовать ее другим
пользователям.
Примечание: те, кто создаст новую
версию переноса MySQL, имеют право
размножать и распространять на
условиях лицензии GPL, но это не делает
их обладателями авторского права на
MySQL.
Для сервера необходима рабочая
библиотека Posix-потоков. Под
операционной системой Solaris 2.5 мы
используем потоки Sun PThreads ("родная"
поддержка потоков в версии 2.4 и более
ранних не является достаточно
хорошей), а под Linux мы используем
LinuxThreads, разработку Ксавье Лероя (Xavier
Leroy, <Xavier.Leroy@inria.fr> ).
При переносе на новый вариант Unix без
хорошей поддержки собственных
потоков наиболее трудной частью
является перенос потоков MIT-pthreads. См.
mit-pthreads/README и Programming POSIX
Threads (Программирование POSIX-потоков)
(http://www.humanfactor.com/pthreads/).
В состав поставки MySQL входит
исправленная версия Pthreads Провензано
(Provenzano) от MIT (см. веб-страницу MIT Pthreads
на
http://www.mit.edu:8001/people/proven/pthreads.html).
Эту версию можно применять для
операционных систем, не имеющих
POSIX-потоков.
Можно использовать и другой пакет
потоков пользовательского уровня - FSU
Pthreads
(страница
FSU Pthreads). Эта реализация
применяется для переноса SCO.
Для ознакомления этими проблемами и
анализа их следует изучить программы
thr_lock.c и thr_alarm.c
в каталоге mysys .
И сервер, и клиент нуждаются в
работающем компиляторе C++ (мы
используем gcc , испытывали
также SPARCworks). Еще одним работающим
компилятором является Irix
cc .
Для компиляции только клиентской
части используйте ./configure
--without-server .
Компиляция отдельно серверной части
в настоящее время не поддерживается,
и добавлять такую возможность не
планируется до тех пор, пока для
этого не будет веских оснований.
Если необходимо изменить любой
Makefile или скрипт
конфигурации, следует использовать
Automake и Autoconf . Мы
применяли версии automake-1.2 и
autoconf-2.12 .
Ниже перечислены действия,
необходимые для того, чтобы собрать
все заново из базовых файлов:
/bin/rm */.deps/*.P
/bin/rm -f config.cache
aclocal
autoheader
aclocal
automake
autoconf
./configure --with-debug=full --prefix='your installation directory'
# makefiles были сгенерированы для GNU make 3.75 или более новой,
# обозначенной как gmake строчкой ниже
gmake clean all install init-db
Если вы столкнетесь с проблемами
новой версии переноса, то, возможно,
потребуется произвести некоторую
отладку MySQL! See Раздел E.1, «Отладка сервера MySQL».
Примечание: прежде
чем запускать отладку mysqld ,
нужно добиться, чтобы заработала
тестовая программа
mysys/thr_alarm and
mysys/thr_lock , - тогда у вас
появится хотя бы призрачный шанс
получить рабочие потоки.
E.1. Отладка сервера MySQL
Если вы используете в MySQL совершенно
новую функциональную возможность,
то можно попробовать запустить
mysqld с параметром
--skip-new (при этом все новые,
потенциально ненадежные функции
будут заблокированы) или с
параметром --safe-mode - он
отключает ряд оптимизаций, которые
могут вызвать проблемы. See
Раздел A.4.1, «Что делать, если работа MySQL
сопровождается постоянными сбоями».
Если mysqld не хочет
стартовать, то необходимо
посмотреть, не влияют ли на ваши
настройки какие-либо
конфигурационные файлы! Вы можете
проверить аргументы файла
my.cnf с помощью mysqld
--print-defaults и, чтобы запретить их
использование, стартовать
mysqld с параметром
--no-defaults ....
Если для запуска mysqld
требуется большое количество
ресурсов центрального процессора
или памяти, а также в случае
зависания программы можно
использовать команду mysqladmin
processlist status . Эта команда
позволит определить, какой именно
запрос требует столь длительного
времени выполнения. При изучении
проблем, связанных с
производительностью или
трудностями при подсоединении
новых клиентов, иногда полезно
запустить команду mysqladmin -i10
processlist status в другом окне.
Команда mysqladmin debug выводит
в журнальный файл информацию о
применяемых блокировках,
используемой памяти и работе с
запросами запросов - возможно, это
поможет вам решить некоторые
проблемы. Данная команда снабдит
вас полезной информацией даже в том
случае, если код MySQL не был
скомпилирован для отладки!
Если проблема заключается в том, что
некоторые таблицы справляются с
работой все медленнее и медленнее,
то такие таблицы необходимо
попробовать оптимизировать с
помощью команды OPTIMIZE TABLE
или myisamchk . See
Глава 4, Администрирование баз данных. Для
проверки медленных запросов можно
также использовать EXPLAIN .
Кроме того, чтобы решить уникальные
для конкретных условий
эксплуатации проблемы, необходимо
изучить раздел данного руководства,
в котором описывается специфика
определенной операционной системы.
See Раздел 2.6, «Заметки по операционным системам».
E.1.1. Компиляция MySQL для отладки
Иногда в случае каких-либо очень
специфических проблем помогает
отладка MySQL. Для этого необходимо
сконфигурировать сборку MySQL с
параметрами --with-debug или
--with-debug=full . Чтобы
проверить, был ли код MySQL
скомпилирован с возможностью
отладки, нужно запустить команду:
mysqld --help . Если среди опций
присутствует флаг --debug , то
отладка доступна. Кроме того, если
задана возможность отладки,
команда mysqladmin ver выводит
версию mysqld как mysql ...
--debug .
При использовании компиляторов gcc
или egcs рекомендуется следующая
конфигурационная строка:
CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \
-fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
--with-debug --with-extra-charsets=complex
Такая запись позволит избежать
проблем с библиотекой
libstdc++ и исключениями C++
(многие компиляторы имеют проблемы
с исключениями C++ в кодах потоков) и
скомпилировать версию MySQL с
поддержкой всех кодировок.
Если есть подозрение, что может
возникнуть ошибка переполнения
памяти, то можно сконфигурировать
MySQL с параметром
--with-debug=full , чтобы
установить программу контроля
выделения памяти (SAFEMALLOC ).
Однако SAFEMALLOC замедляет
работу системы, поэтому при
возникновении проблем с
производительностью необходимо
запустить mysqld с опцией
--skip-safemalloc . Эта опция
заблокирует проверки переполнения
памяти для каждого вызова
malloc и free .
Если mysqld перестает
падать в аварийном режиме при
компиляции ее с параметром
--with-debug , то, возможно, вы
нашли ошибку в компиляторе или
произошла ошибка синхронизации
внутри MySQL. В этом случае можно
попытаться добавить к переменным
CFLAGS и CXXFLAGS в
приведенной выше конфигурационной
строке -g и не
использовать параметр
--with-debug . Если
mysqld и после этого будет
падать, то можно по меньшей мере
подключить к ней отладчик
gdb или использовать
gdb для core-файла, чтобы
выяснить, что происходит.
Если MySQL сконфигурирован для
отладки, то автоматически
становятся доступными множество
дополнительных функций контроля
надежности, которые отслеживают
состояние mysqld . Если они
обнаруживают что-либо
"неожиданное", то информация об
этом будет записана в поток вывода
stderr , который
safe_mysqld направит в журнал
ошибок! Таким образом, если
возникают какие-либо неожиданные
проблемы с MySQL и при этом доступен
исходный код дистрибутива, то
первое, что необходимо сделать, -
сконфигурировать MySQL для отладки!
(А второе необходимое действие -
это, конечно, послать письмо на
<mysql@lists.mysql.com> и попросить
помощи). Пожалуйста, для всех
сообщений о сбоях или вопросов
относительно используемой версии
MySQL используйте скрипт
mysqlbug !
В поставке MySQL для Windows файл
mysqld.exe по умолчанию
скомпилирован с поддержкой
трассировочных файлов.
E.1.2. Создание трассировочных файлов
Если сервер mysqld не
запускается или если вы можете
вызвать его скорую аварийную
остановку, то для выяснения причин
неполадок можно попытаться
создать трассировочный файл.
Для этого необходимо иметь
mysqld , скомпилированный
для отладки. Проверить,
скомпилирован ли mysqld для
отладки можно, выполнив mysqld
-V . Если номер данной версии
заканчивается на -debug , то
она скомпилирована с поддержкой
трассировочных файлов.
Запустите сервер mysqld с
журналом трассировки в каталоге
/tmp/mysqld.trace (или
C:\mysqld.trace под Windows):
mysqld --debug
Под Windows необходимо также
использовать флаг --standalone ,
чтобы mysqld не стартовал
как сервис:
В окне DOS введите следующее:
mysqld --debug --standalone
После этого можно использовать
клиента командной строки
mysql.exe во втором окне DOS,
чтобы воспроизвести проблему. Для
остановки описанного выше сервера
mysqld следует
воспользоваться командой
mysqladmin shutdown .
Следует учесть, что трассировочный
файл получится очень большим!
Чтобы получить трассировочный
файл меньшего размера, можно
использовать что-нибудь вроде:
mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace
при этом в каталог
/tmp/mysqld.trace будет
выводиться только информация с
наиболее интересными для вас
признаками.
Если вы создаете отчет о подобных
ошибках, то, пожалуйста, присылайте
в соответствующий список рассылки
только те строки из
трассировочного файла, которые, по
вашему мнению, имеют
непосредственное отношение к
ошибке! Те же, кто затрудняются
определить место ошибки, могут
загрузить на ftp трассировочный
файл вместе с отчетом об ошибках по
адресу
ftp://support.mysql.com/pub/mysql/secret/,
чтобы разработчики MySQL могли
взглянуть на него.
Трассировочный файл создается с
помощью пакета DBUG ,
автором которого является Фред Фиш
(Fred Fish). See Раздел E.3, «Пакет DBUG».
E.1.3. Отладка mysqld при помощи gdb
В большинстве операционных систем
можно запускать mysqld под
отладчиком gdb - это
позволяет получить больше
информации при аварийных
остановках mysqld ,
С некоторыми более старыми
версиями gdb под Linux, чтобы
обеспечить возможность отладки
потоков mysqld , необходимо
использовать run --one-thread . В
этом случае в каждый момент
времени доступен для отладки
только один поток. Нам остается
только рекомендовать вам как можно
быстрее заменить старые версии
отладчика на версию gdb 5.1,
поскольку отладка потоков в этой
версии работает намного лучше!
При работе mysqld под
отладчиком gdb необходимо
заблокировать трассировку стеков
при помощи --skip-stack-trace , что
обеспечит возможность выявить
ошибки сегмантацию внутри
gdb .
Если постоянно подсоединяются
новые пользователи, то отладка MySQL
под gdb может оказаться
достаточно сложным делом,
поскольку gdb не
освобождает память, занимаемую
старыми потоками. Эту проблему
можно устранить, запустив
mysqld с параметрами -O
thread_cache_size='max_connections+1' . В
большинстве случаев даже простое
использование -O
thread_cache_size=5 может очень
помочь!
Для получения дампа оперативной
памяти под Linux, если mysqld
падает по сигналу SIGSEGV ,
можно запустить mysqld с
опцией --core-file . Этот файл
оперативной памяти (core) можно
использовать для обратной
трассировки при выявлении причин
останова mysqld :
shell> gdb mysqld core
gdb> backtrace full
gdb> exit
See Раздел A.4.1, «Что делать, если работа MySQL
сопровождается постоянными сбоями».
При использовании версии
gdb 4.17.x или выше под Linux
необходимо установить в текущем
каталоге файл .gdb со
следующей информацией:
set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint
Если при отладке потоков с помощью
gdb возникают проблемы,
необходимо загрузить версию
gdb 5.x и попробовать
использовать ее вместо прежней.
Новая версия отладчика
gdb обеспечивает
значительно улучшенную обработку
потоков!
Ниже приводится пример отладки
mysqld:
shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Делайте это при аварийной остановке mysqld
Включите полученный вывод в
письмо, сгенерированное с помощью
mysqlbug , и пошлите это
письмо по адресу
<mysql@lists.mysql.com> .
Если mysqld зависает, можно
попробовать использовать
некоторые системные средства
наподобие strace или
/usr/proc/bin/pstack для
выяснения, где именно произошло
зависание mysqld .
strace /tmp/log libexec/mysqld
Если используется интерфейс Perl
DBI , то можно получить
отладочную информацию, используя
метод trace или установив
переменную окружения
DBI_TRACE . See
Раздел 8.2.2, «Интерфейс DBI ».
E.1.4. Использование трассировки стека
В некоторых операционных системах
журнал ошибок в случае смерти
mysqld будет содержать
трассировку стека. Эти данные
можно использовать для выяснения,
где (и, может быть, почему) умер
mysqld (see Раздел 4.9.1, «Журнал ошибок»).
Для получения трассировки стека не
следует компилировать
mysqld с опцией
-fomit-frame-pointer для
gcc (see
Раздел E.1.1, «Компиляция MySQL для отладки»).
Если файл ошибок содержит
что-нибудь похожее на следующее:
mysqld got signal 11;
The manual section 'Debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attemping 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 range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686
то можно определить, где произошла
остановка mysqld . Для этого
нужно выполнить следующие
действия:
Скопируйте приведенные выше
числовые значения в файл,
например mysqld.stack .
Создайте файл символов для
сервера mysqld :
nm -n libexec/mysqld > /tmp/mysqld.sym
Следует учесть, что во многих
бинарных поставках MySQL
приведенный выше файл с именем
mysqld.sym.gz уже имеется. В
этом случае необходимо
распаковать его следующим
образом:
gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
Выполните resolve_stack_dump -s
/tmp/mysqld.sym -n mysqld.stack , чтобы
вывести место остановки
mysqld . Если и это не
поможет определить причину
останова mysqld , то
следует сделать отчет об ошибке
и включить в него данный вывод с
комментарием. Следует учитывать,
однако, что в большинстве
случаев наличие лишь только
трассировки стеков не поможет
нам определить причину данной
проблемы. Чтобы иметь
возможность локализовать данный
сбой или рекомендовать обходной
путь, нам, как правило,
необходимо знать, какой именно
запрос привел к остановке mysqld и,
желательно, иметь контрольный
пример, чтобы мы могли
воспроизвести данную проблему!
See Раздел 1.8.1.3, «Как отправлять отчеты об ошибках или
проблемах».
E.1.5. Использование журналов для
определения причин ошибок в mysqld
Обратите внимание: перед запуском
mysqld с --log
необходимо проверить все
используемые таблицы с помощью
myisamchk (see
Глава 4, Администрирование баз данных).
Если демон mysqld умрет или
зависнет, следует запустить
mysqld с опцией
--log . Если аварийное
завершение mysqld снова
повторится, то можно исследовать
часть журнала, относящуюся к
запросу, убившему mysqld .
При использовании опции
--log без имени файла данный
журнал хранится в каталоге базе
данных как `hostname`.log . В
большинстве случаев именно
последний запрос в системном
журнале приводит к смерти
mysqld , но при возможности
лучше в этом убедиться:
перезапустите mysqld и
выполните найденный запрос из
командной строки mysql .
Если запрос выполняется, то
следует протестировать все
сложные запросы, которые не
завершились.
Можно также попробовать выполнить
команду EXPLAIN для всех
выражений SELECT , которые
занимают длительное время, чтобы
убедиться, что mysqld
правильно использует индексы. See
Раздел 5.2.1, «Синтаксис оператора EXPLAIN
(получение информации о
SELECT )».
Запросы, требующие слишком
длительного времени для
выполнения, можно выявить,
запустив mysqld с
параметром --log-slow-queries . See
Раздел 4.9.5, «Журнал медленных запросов».
Если в журнале ошибок (обычно он
имеет имя `hostname`.err )
присутствует запись "mysqld
restarted ", то у вас есть шанс
найти запрос, вызывающий смерть
mysqld . В этом случае
необходимо проверить все таблицы с
помощью команды myisamchk (see
Глава 4, Администрирование баз данных) и
проанализировать запросы в
журналах MySQL, чтобы определить,
какой из них не работает. Если
такой запрос найден, прежде всего
необходимо попытаться сделать
апгрейд MySQL до новейшей версии.
Если же это не помогает и нет
ничего похожего в архиве списка
рассылки mysql , пришлите
отчет о данном сбое по адресу
<mysql@lists.mysql.com> . Ссылки на
архивы списка рассылки доступны по
адресу
http://lists.mysql.com/.
Если демон mysqld был
запущен с параметром
myisam-recover , то MySQL
автоматически проверяет и
пытается восстановить таблицы MyISAM
(если они отмечены как "таблица не
закрыта правильно" или "таблица
повреждена"). В этом случае MySQL
запишет в файл hostname.err
предупреждение: "Warning: Checking table
... ", за которым следует
"Warning: Repairing table ", если
данную таблицу следует исправить.
Если таких ошибок в журнале много,
а mysqld перед этим не
умирал со сбоем, то что-то работает
неправильно и необходимы
дальнейшие исследования. See
Раздел 4.1.1, «Параметры командной строки
mysqld ».
Конечно, неожиданная смерть
mysqld - событие
малоприятное, но в этом случае
следует не изучать сообщения
"Checking table... ", а попытаться
найти причины остановки
mysqld .
E.1.6. Создание контрольного примера при
повреждении таблиц
Когда таблицы оказываются
поврежденными или mysqld
всегда дает сбой после некоторых
команд, то можно провести
испытания (если данный сбой
воспроизводим). Для этого нужно
выполнить следующие действия:
Остановите демон MySQL (с помощью
команды mysqladmin shutdown ).
Сделайте резервную копию таблиц
(в качестве меры
предосторожности на случай, если
процесс исправления таблиц
пройдет некорректно, хотя это и
маловероятно).
Проверьте все таблицы с помощью
команды myisamchk -s
database/*.MYI . Исправьте
некорректные таблицы с помощью
команды myisamchk -r
database/table.MYI .
Создайте еще раз резервные копии
этих таблиц.
Переместите (или удалите совсем)
все старые журнальные файлы из
каталога данных MySQL, если нужно
освободить больше места.
Запустите mysqld с
--log-bin (see
Раздел 4.9.4, «Бинарный журнал обновлений»). Если вы хотите
найти запрос, который приводит к
сбою mysqld , то следует
использовать --log --log-bin .
Когда таблица с искажениями
будет получена, остановите
сервер mysqld .
Восстановите систему из
резервной копии.
Перезапустите сервер
mysqld без --log-bin .
Выполните заново команды
mysqlbinlog update-log-file | mysql .
Обновленная запись в журнале
сохраняется в каталоге баз
данных MySQL с именем
hostname-bin.# .
Если в результате
вышеприведенной команды таблицы
опять окажутся поврежденными
или вы можете получить сбой в
работе mysqld , то, значит,
вы нашли повторяющуюся ошибку,
которую можно исправить!
Загрузите эти таблицы и запись
из двоичного журнала по адресу
ftp://support.mysql.com/pub/mysql/secret/
и пошлите письмо с описанием
данной проблемы на
bugs@lists.mysql.com или (если
вы являетесь коммерческим
пользователем) на
support@mysql.com - и команда
разработчиков MySQL устранит
ошибку настолько быстро,
насколько это возможно.
Для локализации проблемы можно
также использовать скрипт
mysql_find_rows , чтобы просто
выполнить ряд обновляющих команд.
E.2. Отладка клиента MySQL
Чтобы иметь возможность отладки
клиента MySQL с помощью встроенного
отладчика, необходимо
сконфигурировать сборку MySQL с
--with-debug или
--with-debug=full . See
Раздел 2.3.3, «Типичные опции configure ».
Перед запуском клиента следует
установить переменную окружения
MYSQL_DEBUG :
shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell> export MYSQL_DEBUG
Это заставит клиента генерировать
трассировочный файл в
/tmp/client.trace .
Если существуют проблемы с кодом
конкретного клиента, необходимо
попытаться соединиться с сервером и
послать запрос, используя другой
заведомо работоспособный клиент.
Это следует делать при работе
mysql в режиме отладки
(предполагается, что данный
экземпляр MySQL скомпилирован с
возможностью отладки):
shell> mysql --debug=d:t:O,/tmp/client.trace
приведенный выше вызов снабдит вас
полезной информацией для отчета об
ошибках. See Раздел 1.8.1.3, «Как отправлять отчеты об ошибках или
проблемах».
Если ваш клиент, имея "правильный" на
первый взгляд код, отказывается
устойчиво работать, необходимо
проверить, соответствует ли
включаемый файл mysql.h
файлу вашей библиотеки
mysql . Очень
распространенная ошибка
заключается в том, что используется
старый файл mysql.h из MySQL
старой установки с новой
библиотекой MySQL.
Сервер MySQL и большинство клиентов
MySQL компилируются с пакетом
DBUG , автором первой версии
которого является Фред Фиш (Fred Fish).
При конфигурации MySQL в отладочном
режиме этот пакет дает возможность
получить трассировочный файл для
отладки программы. See
Раздел E.1.2, «Создание трассировочных файлов».
Чтобы воспользоваться пакетом
отладки, следует в вызове программы
задать опцию --debug="..." или
-#...
Большинство программ MySQL по
умолчанию имеют отладочную строку,
которая будет использована, если не
задана опция --debug . По
умолчанию трассировочный файл
обычно находится в
/tmp/имя_программы.trace под
Unix и в \имя_программы.trace
под Windows.
Строка управления отладкой
представляет собой
последовательность разделенных
двоеточиями полей, как в следующем
примере:
<field_1>:<field_2>:...:<field_N>
Каждое поле состоит из
обязательного флагового символа, за
которым следует необязательный
символ "," и разделенный запятыми
список модификаторов:
flag[,modifier,modifier,...,modifier]
В настоящее время распознаются
следующие символы флагов:
Ниже представлены некоторые
примеры строк управления отладкой,
которые можно применять в командной
строке оболочки (символ
"-# " обычно используется
для внедрения управляющей строки в
программу):
-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace
В MySQL обычно применяются следующие
дескрипторы для вывода (совместно с
опцией d ):
enter,exit,error,warning,info и
loop .
В настоящее время MySQL поддерживает
только табличную блокировку для
таблиц типов ISAM/MyISAM и HEAP, страничную
блокировку для таблиц BDB и строковую
блокировку для таблиц InnoDB (see
Раздел 5.3.1, «Как MySQL блокирует таблицы»). Для таблиц MyISAM
можно произвольным образом
сочетать команды INSERT и
SELECT без блокировок,
поскольку поддерживается
управление версиями (Versioning).
Начиная с версии 3.23.33 имеется
возможность анализировать
конфликты и конкуренцию блокировок
таблиц в системе. Это делается путем
проверки переменных
Table_locks_waited и
Table_locks_immediate .
Если вы хотите использовать тип
таблиц с блокировкой уровня записи,
то прежде, чем принимать такое
решение, следует посмотреть, что
делает данное приложение и какая
принята модель выборки/обновления
данных.
Аргументы в пользу строковой
блокировки:
Меньше конфликтов блокировок при
обращении к различным строкам из
множества потоков.
Меньше изменений при откатах.
Возможна блокировка одной строки
на длительное время.
Аргументы против строковой
блокировки
Требуется больше памяти, чем при
страничной или табличной
блокировке.
При использовании большой части
таблицы строковая блокировка
работает медленнее в сравнении с
блокировкой на уровне страниц или
таблиц, поскольку требуется
производить намного больше
блокировок.
Определенно хуже других
блокировок, если часто
выполняется операция GROUP
BY на значительной части
данных или если приходится
сканировать всю таблицу.
Для блокировок более высокого
уровня также проще осуществить
поддержку различных типов
блокировок для настройки
приложения, поскольку для них
затраты на блокировку менее
заметны, чем для строкового
уровня блокировки.
Блокировки на уровне таблиц лучше,
чем блокировки
страничного/строкового уровня в
следующих случаях:
Когда производится главным
образом чтение.
При чтении и обновлении для
строго заданных ключей; при
обновлении или удалении строки,
которая может быть извлечена
чтением одного ключа:
UPDATE table_name SET column=value WHERE unique_key#
DELETE FROM table_name WHERE unique_key=#
SELECT с INSERT (и
очень мало операций UPDATE
и DELETE ).
Выполняется много операций
просмотра и группировки GROUP
BY на всей таблице без записи.
Другие возможности, кроме
строчного/страничного уровня
блокирования:
Управление версиями (Versioning), подобно
тому, как это делается в MySQL для
параллельных вставок. При этом один
из пользователей может выполнять
операцию записи в то же время, когда
несколько пользователей производят
чтение. Это означает, что данная
база данных/таблица поддерживает
различные представления для данных
в зависимости от того, когда
произошло обращение к ним.
Существуют и другие названия этой
возможности - перемещение по
времени (time travel), метод копирования в
момент записи (copy on write) или метод
копирования по запросу (copy on demand).
Копирование по запросу во многих
случаях значительно лучше, чем
страничный или строковый уровень
блокировки; однако в наиболее
неблагоприятном варианте этот
метод требует намного больше
памяти, чем при использовании
обычных блокировок.
Вместо использования блокировок
строкового уровня можно применять
блокировки уровня приложения
(подобно get_lock/release_lock в MySQL). Конечно,
такие блокировки годятся только для
корректно работающих приложений.
Если речь идет о конкретном
приложении, то обычно можно с
уверенностью сказать, какой тип
блокировки лучше всего в нем
использовать, однако для общего
случая такой вывод сделать
практически невозможно: все зависит
от конкретного приложения, причем
для различных частей приложения
могут требоваться различные типы
блокировок.
Ниже приводится несколько советов
по блокировкам в MySQL:
Большинство веб-приложений
выполняют большое количество
выборок, очень мало удалений,
обновления главным образом по
ключам и вставки в некоторые
специальные таблицы. Базовая
установка MySQL очень хорошо
настроена для этого.
Одновременный доступ пользователей
не представляет проблем, если не
происходит смешивания обновлений и
выборок, требующих проверки
нескольких строк в одной и той же
таблице.
В случае сочетания вставок и
удалений в одной и той же таблице
очень полезно применять INSERT
DELAYED .
Для повышения скорости можно также
использовать LOCK TABLES
(несколько обновлений в рамках
одной блокировки выполняются
намного быстрее, чем обновления без
блокировок). Целесообразно также
распределять данные по различным
таблицам.
Иногда проблемы со скоростью при
блокировках таблиц в MySQL удается
решить преобразованием ряда таблиц
в таблицы типа InnoDB или BDB. See
Раздел 7.5, «Таблицы InnoDB ». See Раздел 7.6, «Таблицы BDB или BerkeleyDB».
Большое количество различных
аспектов настройки приложения
рассмотрено в разделе данного
руководства, посвященном
оптимизации (see Раздел 5.2.12, «Другие советы по оптимизации»).
E.5. Замечания по потокам RTS
При попытке применить пакеты
потоков RTS с MySQL автору пришлось
столкнуться со следующими
проблемами:
В этих пакетах используются старые
версии большинства вызовов POSIX,
поэтому очень утомительно
создавать оболочки (wrapper) для всех
функций. На мой взгляд, было бы легче
изменить библиотеки этих потоков в
соответствии с современной
спецификацией POSIX.
Некоторые оболочки уже написаны
(чтобы получить более подробную
информацию, обращайтесь к
mysys/my_pthread.c ).
Следует изменить, по меньшей мере,
следующие аспекты:
В pthread_get_specific должен
использоваться один аргумент, а в
sigwait - два аргумента.
Многие функции (по крайней мере,
pthread_cond_wait ,
pthread_cond_timedwait ) должны
возвращать код ошибки или ошибку.
Сейчас они возвращают -1 и
устанавливают errno .
Еще одна проблема заключается в том,
что потоки пользовательского
уровня используют сигнал
ALRM , преждевременно
прекращающий работу многих функций
(read, write, open... ). MySQL должен
повторять попытку выполнить такие
вызовы в случае прерывания, но это
не так легко проверить.
Наиболее значительная из
нерешенных проблем заключается в
следующем:
Чтобы получать alarm на уровне потока,
я изменил mysys/thr_alarm.c -
чтобы ожидать alarm с помощью функции
pthread_cond_timedwait() . Однако
оказалось, что это приводит к
преждевременному прекращению
работы с ошибкой EINTR .
Чтобы понять, почему так получается,
я пытался отладить библиотеку
потока, но не смог найти никакого
простого решения.
Для тех, кто хочет попробовать
использовать MySQL с потоками RTS, я
предлагаю следующее:
Измените функции, используемые
MySQL из библиотеки потоков для POSIX.
Это не должно занять много
времени.
Скомпилируйте все библиотеки с
-DHAVE_rts_threads .
Скомпилируйте thr_alarm .
Если существуют некоторые
небольшие отличия в реализации,
то они могут быть устранены
изменением my_pthread.h и
my_pthread.c .
Запустите thr_alarm . Если
программа выполняется без
каких-либо предупреждений,
сообщений об ошибках или об
аварийном выходе, значит, вы на
правильном пути. Ниже приводится
успешный прогон программы под
Solaris:
Main thread: 1
Thread 0 (5) started
Thread: 5 Waiting
process_alarm
Thread 1 (6) started
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 1 (1) sec
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 2 (2) sec
Thread: 6 Simulation of no alarm needed
Thread: 6 Slept for 0 (3) sec
Thread: 6 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 4 (4) sec
Thread: 6 Waiting
process_alarm
thread_alarm
Thread: 5 Slept for 10 (10) sec
Thread: 5 Waiting
process_alarm
process_alarm
thread_alarm
Thread: 6 Slept for 5 (5) sec
Thread: 6 Waiting
process_alarm
process_alarm
...
thread_alarm
Thread: 5 Slept for 0 (1) sec
end
E.6. Различия между разными потоковыми
пакетами
Работа MySQL в значительной степени
зависит от используемого
потокового пакета. Таким образом,
при выборе хорошей платформы для MySQL
потоковый пакет играет очень важную
роль.
Существуют по меньшей мере три типа
потоковых пакетов:
Пользовательские потоки в одном
процессе. Переключение потоков
осуществляется сигналами (alarm) и
библиотека потоков управляет
всеми функциями, не
поддерживающими потоки, с помощью
блокировок. Операции чтения,
записи и выборки обычно
управляются программой выбора
потоков, которая переключает их
на другой поток, если текущий
должен ожидать данные (речь идет о
вызове select). Пакеты
пользовательских потоков могут
быть интегрированы в стандартные
библиотеки (FreeBSD- и BSDI-потоки).
Такие интегрированные пакеты
требуют меньше затрат в сравнении
с потоковыми пакетами, которые
должны обрабатывать все
ненадежные вызовы (MIT-pthreads, FSU Pthreads
и потоки RTS). В некоторых средах
(например SCO) все системные вызовы
поддерживают потоки, так что
обработка может быть выполнена
очень просто (FSU Pthreads под SCO).
Недостатки такого метода:
поскольку все вызовы, для которых
установлены соответствия,
занимают мало времени, очень
сложно контролировать обработку
всех ситуаций. Обычно существуют
также системные вызовы, не
обрабатываемые потоковым пакетом
(такие как MIT-pthreads и сокеты).
Диспетчеризация потоков не
всегда является оптимальной.
Пользовательские потоки в
раздельных процессах.
Переключение потоков
производится ядром и все данные
используются совместно всеми
потоками. Потоковый пакет
управляет стандартными вызовами
потоков, чтобы обеспечить
совместное использование данных
этими потоками. Такой метод
используется в LinuxThreads. Недостатки
этого метода: масса процессов;
медленное создание потока. Если
один поток умирает, то остальные
обычно зависают и необходимо их
уничтожать перед перезапуском.
Переключение потоков отчасти
затратно.
Потоки ядра. Переключение потоков
управляется потоковой
библиотекой или ядром и
происходит очень быстро. Все
делается в одном процессе, но для
некоторых систем ps
может показывать разные потоки.
Если один из потоков неожиданно
умрет, то происходит аварийное
прерывание всего процесса.
Большинство системных вызовов
поддерживают потоки и должны
требовать очень небольших затрат.
С потоками ядра работают Solaris, HP-UX,
AIX и OSF/1.
В некоторых системах управление
потоками ядра осуществляется путем
интеграции потоков
пользовательского уровня в
системные библиотеки. В подобных
случаях переключение потоков может
осуществляться только данной
потоковой библиотекой, и ядро
фактически "не в курсе событий".
|
|