Почему происходит сбой таблиц MySQL? Как мне это предотвратить?

9

Я - администратор сайта Moodle, у которого повреждена таблица «Пользователи», и она стала непригодной для использования.

К счастью, простой REPAIR TABLE mdl_userзаставил это работать снова. Дело в том, что я не знаю, почему он действительно рухнул и сделал его непригодным для использования, и я хочу убедиться, что в следующий раз я буду лучше подготовлен.

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

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

Эти таблицы являются utf8_general_ci и используют MyISAM.

Почему происходит сбой таблицы MySQL? Что я могу сделать, чтобы этого не случилось?

AeroCross
источник

Ответы:

11

Таблице MyISAM довольно легко выйти из строя.

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

Если вы запустите mysql, а число в заголовке не совпадает с количеством фактических дескрипторов файла, mysqld рассматривает таблицу как сбойную.

Если простой REPAIR TABLE mdl_userзаставляет его снова работать каждый раз без потери данных, это может означать, что у вас есть сайт с очень высокой посещаемостью, который пишет на mdl_user.

Если этого требуют десятки таблиц REPAIR TABLE, я бы преобразовал все таблицы в InnoDB. Однако, если mdl_userтаблица является единственной таблицей с этой проблемой, есть кое-что, что вы можете сделать (для этого примера, скажем, база данных moodle);

Если вы хотите, чтобы все таблицы оставались как MyISAM

ШАГ 01: Создание сценария ремонтной таблицы

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

ШАГ 02: Объявите сценарий восстановления как файл запуска

Добавьте это в /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

ШАГ 03: Перезапустите MySQL

Каждый перезапуск mysql вызовет скрипт восстановления таблицы

Если вы хотите, чтобы все таблицы стали InnoDB

Запустите этот код, чтобы создать сценарий массового преобразования таблиц MyISAM в InnoDB, и просмотрите его.

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

Если вы удовлетворены содержимым скрипта преобразования, запустите его

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

ОБНОВЛЕНИЕ 2012-03-15 14:00 ПО ВОСТОЧНОМУ ВРЕМЕНИ

@Kevin , при использовании MyISAM, что если у вас недостаточно свободного места на диске?

Вот что нужно учитывать: в соответствии с MySQL 5.0 Certification Study Guide ,

введите описание изображения здесь

пункт № 11 говорит следующее на страницах 408, 409, раздел 29.2:

Если при добавлении строк в таблицу MyISAM не хватает места на диске, ошибки не возникает. Сервер приостанавливает операцию до тех пор, пока не освободится место, а затем завершает операцию.

Когда у вас заканчивается свободное место на диске, не просто завершите работу или убейте mysql. Количество дескрипторов открытых файлов в любых используемых в настоящее время MyISAM не будет очищено. Таким образом, таблица MyISAM помечена как сбойная. Если вы можете освободить дисковое пространство в томе данных, когда mysqld все еще работает, mysqld займется защитой, как только освободится дисковое пространство.

RolandoMySQLDBA
источник
Отличный ответ. Я не знал бит файловых дескрипторов, и вы уже решили, как я могу предотвратить (или автоматически исправить), если что-то пойдет не так. Любое предложение по безопасности, если сайт на самом деле делает много записей в mdl_user (или любую другую таблицу)?
АэроКросс
Вы должны сделать три вещи: 1) увеличить ОЗУ, 2) увеличить max_connections, 3) переключиться на InnoDB.
RolandoMySQLDBA
Нуб здесь. Где я могу «запустить» этот код? Из файла, загруженного на сервер, или из какой-то командной строки?
UncaughtTypeError
0

Я также администрирую сайт Moodle на MySQL, и наиболее распространенная причина повреждения таблиц для нас - это нехватка места на диске.

Kevin
источник
@RolandoMySQLDBA - да, конечно, проблема с дисковым пространством (связана с некоторыми другими процессами и философией управления в целом). К сожалению, мы не видим, что проблема решается сама по себе, когда очищается пространство, или она не решается сама собой в достаточно своевременное время. В ответ я просто указал, что с нашим экземпляром moodle / mysql проблемы с дисковым пространством могут вызвать сбои таблиц, независимо от того, что должен делать mysql / myisam.
Кевин
-3

Я нашел одну хорошую строку для преобразования всех таблиц в InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName
Дмитрий
источник
Код может подойти для этого, но он не отвечает на первый вопрос (Почему происходит сбой таблицы MySQL?). Если вы имеете в виду, что он отвечает на вторую часть (Как это предотвратить?), Добавьте еще несколько пояснений, пожалуйста.
ypercubeᵀᴹ
Также добавьте больше деталей. Запустит ли это преобразование всех таблиц в базе данных? Или весь сервер? Что произойдет, если таблица не преобразуется и мы получим ошибку? Возможно, мы получим несколько преобразованных таблиц, а некоторые останемся в MyiSAM? В общем, что еще нужно рассмотреть администратору БД перед выполнением этого?
ypercubeᵀᴹ