Pull to refresh

Исправление работы MySQL при поломке innoDB-таблиц

Reading time3 min
Views56K
Здравствуйте!
mysql innodb
Я (быть может, как и вы) — разработчик сайтов, и мне, чтобы все мои наработки не потерялись нужен SVN. А так как я работаю не один, то еще, как минимум, и общая БД. Несколько лет назад мы приобрели NAS-сервер Synology DS-101 (Tom`s Guide или Nix), устроили там хранилище, включили базу (правда, MySQL4). Несколько лет служил он нам верой и правдой, пережил приход пьяных электриков (когда нас сначала подключили на 380В, а потом спохватились — почти все погорело), но вот… несколько недель назад база не хотела загружаться. Пришлось исправлять.

Все бы ничего, если бы этот случай не повторился…


В первый раз на сервер в срочном порядке была залита новая прошивка, разрешающая доступ по telnet. Не забываем, там очень сильно урезанный линукс — Linux version 2.4.22-uc0 — установка чего-либо производится через telnet, а по SSH система требует рута, под которым не пускает. После пары часов была выявлена проблема — не запускается именно демон mysqld. Попытавшись вручную запустить mysqld, вылезала ошибка, она же собственно была и в логах, следующего содержания:

100209 14:04:59 mysqld started
100209 14:05:00 [Warning] Setting lower_case_table_names=2 because file system for /volume1/@database/mysql/ is case insensitive
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
InnoDB: You may have to recover from a backup.
100209 14:05:00 InnoDB: Page dump in ascii and hex (16384 bytes): len 16384; hex (...большой дамп ~ на 16КБ...)InnoDB: End of page dump
100209 14:05:04 InnoDB: Page checksum 2825884538, prior-to-4.0.14-form checksum 2024336829
InnoDB: stored checksum 1598293605, prior-to-4.0.14-form stored checksum 2024336829
InnoDB: Page lsn 0 2531807, low 4 bytes of lsn at page end 2531807
InnoDB: Page number (if stored to page already) 5,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also dev.mysql.com/doc/mysql/en/Forcing_recovery.html
InnoDB: about forcing recovery.
InnoDB: Ending processing because of a corrupt database page.
100209 14:05:04 mysqld ended


Получается, что я не мог запустить mysqld без того, чтобы исправить порушенные таблицы, и не мог исправить таблицы без запуска демона.
Полазив по интернету, нашлось два пути решения данной проблемы:
Первый и Официальный — dev.mysql.com
Второй и менее официальный — mysqlperformanceblog.com

Первый вариант решения проблемы подразумевает запуск демона так:

mysqld --innodb_force_recovery=4

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

Prevent insert buffer merge operations. If they would cause a crash, do not do them. Do not calculate table statistics.
(Предотвращать операции слияния вставки буфера. Если они вызывают аварию, не выполнять их. Не считать статистику таблиц)


Если короче — то чтобы сдампить таблицы, и перераспределить место на диске под таблицы innodb.
С этим параметром сервер запускается, но CHECK TABLE показывает OK. OPTIMIZE TABLE для innodb-таблиц не поддерживается движком.

Нужно каким-либо образом обратиться к таблицам innodb (например, создать INSERT-запрос) — mysqld перераспределит место. После перераспределения места мы сможем запустить демон myslqd в нормальном режиме, т.е. просто перезапустив NAS-сервер (это в нашем случае). Не могу сказать, что какие-либо данные недоступны — сдампил без ошибок и проблем. Возможно, в таком случае мы все же что-то теряем — пусть меня поправят специалисты.

Второй вариант (с майэскулперформансблога) представляет собой запуск демона с innodb_force_recovery=1, создание <new_table> c движком MyISAM и попытку загнать туда все записи из таблицы с innodb. Вкратце описывается это так:

CREATE TABLE <new_table> LIKE <crashed_table>;
INSERT INTO <new_table> SELECT * FROM <crashed_table>;


И переименовываем.

Если же нужно найти именно те строки, на которых он рубится, используется метод нескольких вставок (INSERT IGNORE) в новую таблицу с лимитом. Там все подробно расписано.

Надеюсь, эта маленькая статья кому-то поможет в похожей ситуации, потому как мне первый раз понадобилось достаточно большое время, чтобы все исправить. У меня было время — у вас его может не быть. Также призываю специалистов по MySQL включиться в обсуждение данного вопроса — почему innodb падает.
Tags:
Hubs:
+7
Comments11

Articles

Change theme settings