A.4.1 Что делать, если работа MySQL сопровождается постоянными сбоями
Перед официальным выпуском все версии MySQL тестируются на многих
платформах. Это не означает, что в MySQL совсем нет ошибок, но если они и
есть, то мало, и их не так просто отыскать. В любом случае, столкнувшись с
какой-либо проблемой, всегда полезно попытаться точно определить, что
вызывает аварию системы, - тогда шансы, что проблема будет устранена в
скором времени, станут значительно выше.
Сначала надо попробовать локализовать проблему. Определите, что
происходит: то ли демон mysqld
прекращает работу, то ли проблема связана с
клиентом. Узнать, сколько времени сервер mysqld
уже работает, можно,
выполнив mysqladmin version
. Если mysqld
прекратил выполнение, то для
выяснения причин можно изучить файл `mysql-data-directory/`hostname`.err'
(see section 4.9.1 Журнал ошибок).
Причиной многих аварий MySQL являются поврежденные индексные файлы или
файлы данных. MySQL обновляет данные на диске, используя системный вызов
write()
, после каждой команды SQL и до того, как клиент будет уведомлен о
результате (однако при выполнении с delay_key_write
это не так:
записываются только данные). Отсюда следует, что данные не пострадают даже
в случае аварийного завершения mysqld
, поскольку ОС позаботится о том,
чтобы те данные, которые не сброшены, были записаны на диск. Можно
заставить MySQL сбрасывать все на диск после каждой SQL-команды, запустив
mysqld
с --flush
.
Все это означает, что обычно таблицы не должны повреждаться; исключение
составляют следующие случаи:
-
Кто-нибудь/что-нибудь убьет процесс
mysqld
или выключит машину посреди
операции обновления.
-
Проявила себя ошибка в
mysqld
, вызывающая прекращение его выполнения
посреди операции обновления.
-
Кто-нибудь работает с файлами данных или индексными файлами вне
mysqld
и
при этом не делает блокировку таблиц как следует.
-
Если работает несколько серверов
mysqld
с одними данными на системе без
пристойной поддержки блокировок файловой системы (обычно реализуется
демоном lockd
) или если выполняется несколько серверов со --skip-locking
-
Существует поврежденный индексный файл или файл данных, содержащий очень
неправильные данные, которые вводят в заблуждение
mysqld
.
-
Проявила себя в коде записи данных. Это маловероятно, но в общем случае
возможно. В этом случае можно попробовать изменить формат файла на
соответствующий другому обработчику баз данных, используя
ALTER TABLE
на
исправленной копии таблицы!
Поскольку найти причину сбоя всегда непросто, сначала можно попробовать
выяснить, что из того, что работает у других, вызывает аварии у вас.
Попытайтесь выполнить следующие действия:
-
Избавьтесь от
NULL
в качестве значений по умолчанию (это можно увидеть в
DESCRIBE table_name
)
-
Используйте
truncate()
для округления всех отрицательных значений к
ближайшему целому.
-
Остановите демон
mysqld
с помощью mysqladmin shutdown
, выполните
myisamchk --silent --force */*.MYI
на всех таблицах и перезапустите
демон mysqld
. Этим гарантируется безошибочность исходного состояния
(see section 4 Администрирование баз данных).
-
Используйте
mysqld --log
и попытайтесь определить по информации в
журналах, не вызвано ли прекращение работы сервера каким-либо
специфическим запросом. Около 95% всех ошибок обусловлены конкретными
запросами! Обычно это один из последних запросов в журнальном файле
непосредственно до перезапуска MySQL (see section 4.9.2 Общий журнал запросов). Если вы сумеете повторно вызвать отказ MySQL при помощи одного
из запросов, даже когда таблицы были проверены непосредственно перед
выполнением запроса, то возможна локализация ошибки и подготовка
отчета об ошибке! see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах.
-
Попробуйте сделать контрольный тест, который мы могли бы использовать,
чтобы воспроизвести проблему (see section E.1.6 Создание контрольного примера при повреждении таблиц).
-
Попробуйте выполнить входящий в поставку тест
mysql-test
и тесты
производительности MySQL (see section 9.1.2 Пакет тестирования MySQL). Эти тесты
должны довольно хорошо протестировать MySQL. Вы можете также добавить
в тесты производительности код для имитации своего приложения! Тесты
производительности можно найти в каталоге bench в поставке с исходными
кодами или, в случае бинарной поставки, в подкаталоге sql-bench
своего
каталога инсталляции MySQL.
-
Попробуйте
fork_test.pl
и fork2_test.pl
.
-
Если что-то пойдет не так, то собирать информацию о возможных ошибках
будет значительно проще, если MySQL сконфигурирован для отладки.
Переконфигурируйте MySQL, применяя
configure
с опцией --with-debug
или
--with-debug=full
, и затем перекомпилируйте (see section E.1 Отладка сервера MySQL).
-
Конфигурирование MySQL в отладочном режиме приводит к включению
безопасного распределителя памяти, который может находить некоторые
ошибки. Помимо этого, отладочная версия выдает большое количество
информации о том, что происходит.
-
Выясните, применены ли последние патчи для используемой операционной
системы.
-
Используйте опцию
--skip-locking
к mysqld
. На некоторых системах
менеджер блокировок lockd
не работает как следует; опция
--skip-locking
указывает mysqld
не применять внешнюю блокировку (это
означает, что нельзя выполнять два сервера mysqld
на одних данных и
что необходимо быть осторожным при использовании myisamchk
, однако
применение этой опции может принести большую пользу для целей
тестирования).
-
Если возникнет ситуация, когда кажется, что
mysqld
запущен, но не
отвечает, стоит попробовать выполнить mysqladmin -u root processlist
.
Иногда mysqld
не является зависшим, даже если кажется, что это так.
Проблема может быть в том, что все соединения используются, или,
возможно, имеется некая внутренняя проблема с блокировками. mysqladmin
processlist
обычно способна установить соединение даже в таких случаях
и выдать полезную информацию о текущем количестве соединений и их
состоянии.
-
Выполните команду в отдельном окне
mysqladmin -i 5 status
или
mysqladmin -i 5 -r
для вывода статистики, пока будут выполняться
другие запросы.
-
Попробуйте выполнить следующие действия:
-
Запустите
mysqld
в gdb
(или в другом отладчике).
See section E.1.3 Отладка mysqld при помощи gdb.
-
Запустите тестовые скрипты.
-
Отобразите стек (
backtrace
) и локальные переменные на трех нижних
уровнях. В gdb
это можно сделать следующими командами после аварийного
завершения mysqld
внутри gdb
:
backtrace
info local
up
info local
up
info local
С помощью gdb
можно также выяснить, какие имеются потоки (посредством info
threads
), и переключиться на определенный поток посредством thread #
, где
#
- номер потока.
-
Попробуйте имитировать работу своего приложения с помощью
Perl-скрипта, который бы вызвал аварийное завершение или неправильное
функционирование MySQL.
-
Отправьте нам обычный отчет об ошибке (see section 1.8.1.3 Как отправлять отчеты об ошибках или проблемах). Любые подробности будут нелишними. Поскольку MySQL
нормально эксплуатируется в очень многих местах, то, возможно, авария
вызвана причиной, которая свойственна только вашему компьютеру
(например, ошибка, связанная с вашими особенными системными
библиотеками).
-
Если возникла проблема с таблицами, имеющими динамическую длину строк,
и не используются столбцы типа
BLOB/TEXT
(а только столбцы типа
VARCHAR
), то можно попробовать изменить все VARCHAR
на CHAR
с помощью
ALTER TABLE
. Это заставит MySQL использовать строки фиксированного
размера. Для строк фиксированного размера понадобится немного
дополнительной памяти, однако они гораздо менее чувствительны к
повреждениям! Сегодняшний код динамических строк без каких бы то ни
было проблем эксплуатируется в MySQL AB по крайней мере 3 года, но в
принципе строки динамической длины более подвержены ошибкам, поэтому
данный рецепт, возможно, сможет вам чем-то помочь!
Add your own comment.