Как отремонтировать таблицу InnoDB?
Мы (очевидно) плохо выполнили нашу базу данных Solaris MySQL прошлой ночью. По крайней мере, некоторые из таблиц InnoDB повреждены, с ошибками отметки времени в журнале транзакций и конкретной ошибкой в повреждении индекса.
Мы знаем об инструментах, доступных для ремонта таблиц MyISAM, но не можем найти ничего для InnoDB.
Примечание: попытка оптимизации таблицы (в моей попытке перестроить поврежденный индекс) приводит к сбою сервера базы данных.
8 ответов
Прежде всего остановите сервер и создайте образ диска. Там нет смысла только один выстрел в этом. Тогда посмотрите здесь.
Остановите ваше приложение... или остановите ваше ведомое устройство, чтобы новые строки не добавлялись
create table <new table> like <old table>;
insert <new table> select * from <old table>;
truncate table <old table>;
insert <old table> select * from <new table>;
перезагрузите ваш сервер или подчиненный
Следующее решение было вдохновлено советами Сандро выше.
Предупреждение: пока это работает для меня, но я не могу сказать, будет ли это работать для вас.
Моя проблема заключалась в следующем: чтение некоторых конкретных строк из таблицы (давайте назовем эту таблицу broken
) будет сбой MySQL. Четное SELECT COUNT(*) FROM broken
убил бы это. Я надеюсь, что у вас есть PRIMARY KEY
на этой таблице (в следующем примере это id
).
- Убедитесь, что у вас есть резервная копия или снимок сломанного сервера MySQL (на тот случай, если вы захотите вернуться к шагу 1 и попробовать что-нибудь еще!)
CREATE TABLE broken_repair LIKE broken;
INSERT broken_repair SELECT * FROM broken WHERE id NOT IN (SELECT id FROM broken_repair) LIMIT 1;
- Повторяйте шаг 3, пока не произойдет сбой БД (вы можете использовать
LIMIT 100000
и затем используйте более низкие значения, пока неLIMIT 1
вылетает в БД). - Посмотри есть ли у тебя все (можешь сравнить
SELECT MAX(id) FROM broken
с количеством строк вbroken_repair
). - В этот момент у меня, очевидно, были все мои строки (кроме тех, которые, вероятно, были дико обрезаны InnoDB). Если вы пропустите несколько строк, вы можете попробовать добавить
OFFSET
кLIMIT
,
Удачи!
Вот решение, предоставленное MySQL: http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
В моем случае сработала простая остановка и перезапуск SQL-сервера.
Примечание. Если ваша проблема в том, что "индекс innodb отмечен как поврежденный"! Тогда простое решение может заключаться в том, чтобы просто удалить индексы и добавить их снова. Эту проблему можно решить довольно быстро без потери каких-либо записей, перезапуска или перемещения содержимого таблицы во временную таблицу и обратно.
Смотрите эту статью: http://www.unilogica.com/mysql-innodb-recovery/ (на португальском языке)
Объясняется, как использовать innodb_force_recovery и innodb_file_per_table. Я обнаружил это после необходимости восстановления разбитой базы данных с одним ibdata1.
Используя innodb_file_per_table, все таблицы в InnoDB создадут отдельный файл таблицы, как MyISAM.
Шаг 1.
Остановить сервер MySQL
Шаг 2.
добавьте эту строку в my.cnf (в windows она называется my.ini)
set-variable=innodb_force_recovery=6
Шаг 3.
удалить ib_logfile0 и ib_logfile1
Шаг 4
Запустите сервер MySQL
Шаг 5
Запустите эту команду:
mysqlcheck --database db_name table_name -uroot -p
После того, как вы успешно исправили разбитую таблицу innodb, не забудьте удалить #set-variable=innodb_force_recovery=6 из my.cnf, а затем снова перезапустить сервер MySQL.