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