====== Восстановление поврежденных таблиц InnoDB ======
error.log
...
InnoDB: Database page corruption on disk or a failed
...
InnoDB: Ending processing because of a corrupt database page.
Для восстановления (бэкапы надо делать!) нужно использовать [[https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_force_recovery|innodb_force_recovery]].
Единственный нормальный перевод по параметрам **innodb_force_recovery** я нашел на сайте [[https://miac.volmed.org.ru/wiki/index.php/Принудительное_восстановление_InnoDB|miac.volmed.org.ru]]. Спасибо большое автору.
**1 SRV_FORCE_IGNORE_CORRUPT (Игнорировать повреждения)**
Позволяет запустить сервер, даже если обнаружаться повреждения базы. Пытаясь сделать **SELECT * FROM tbl_name**, что бы перескочить через поврежденные индексные записи и страницы, что помогает сделать дамп таблиц.
Let the server run even if it detects a corrupt page. Try to make **SELECT * FROM tbl_name** jump over corrupt index records and pages, which helps in dumping tables.
**2 SRV_FORCE_NO_BACKGROUND (Запретить теневые процессы)**
Предотвращает запуск основного подпроцесса. Если сбой произошел во время процесса восстановления, это значение параметра предотвратит это.
Prevent the main thread from running. If a crash would occur during the purge operation, this recovery value prevents it.
**3 (SRV_FORCE_NO_TRX_UNDO)**
Не запускать процесс отката транзакций после восстановления
Do not run transaction rollbacks after recovery.
**4 (SRV_FORCE_NO_IBUF_MERGE)**
Запретить также выполнение insert buffer merge операций. Если они приведут к разрушению, то не делайте их. Не выполняйте подсчет статистики таблиц.
Prevent also insert buffer merge operations. If they would cause a crash, do not do them. Do not calculate table statistics.
**5 (SRV_FORCE_NO_UNDO_LOG_SCAN)**
Не смотреть на логи восстановления, при старте базы данных: InnoDB считает даже незавершенные до выключения транзакции как завершенные.
Do not look at undo logs when starting the database: InnoDB treats even incomplete transactions as committed.
**6 (SRV_FORCE_NO_LOG_REDO)**
Do not do the log roll-forward in connection with recovery.
Starting from MySQL 3.23.53 and 4.0.4, you can **SELECT** from tables to dump them, or **DROP** or **CREATE** a table even if forced recovery is used. If you know that a certain table is causing a crash in rollback, you can drop it. You can use this also to stop a runaway rollback caused by a failing mass import or **ALTER TABLE**. You can kill the mysqld process and **set innodb_force_recovery** to **3** to bring the database up without the rollback, then **DROP** the table that is causing the runaway rollback.
//В обычных условиях база данных не должна использоваться при параметре **innodb_force_recovery**, отличном от нуля//. Как защитная мера, InnoDB не дает пользователям выполнять команды **INSERT**, **UPDATE**, или **DELETE**, когда **innodb_force_recovery** больше 0.
//The database must not otherwise be used with any non-zero value of **innodb_force_recovery**//. As a safety measure, InnoDB prevents users from performing **INSERT**, **UPDATE**, or **DELETE** operations when **innodb_force_recovery** is greater than 0.
==== Ремонт ====
Останавливаем MySQL. Добавляем в ''my.cnf''
port = 5678
innodb_force_recovery = 1
innodb_purge_threads = 0
На время ремонта поменяем порт 3306 на рандомный.
Запускаем MySQL и делаем дамп всех баз
mysqldump –-all-databases > all_db.sql
или дамп только одной базы
mysqldump database_name > database_name.sql
или дамп только одной таблицы
mysqldump database_name table_name > database_table.sql
Далее в зависимости от того, что бэкапили удаляем или всё или базу или таблицу:
дропаем всё - базы, ib_logfile* и ibdata*. ОСТАВЛЯЕМ каталоги **mysql** и **performance_schema**
Удаляем только одну [[https://dev.mysql.com/doc/refman/8.0/en/drop-database.html|базу]]
drop database database_name;
Удаляем только [[https://dev.mysql.com/doc/refman/8.0/en/drop-table.html|таблицу из базы]]
drop table table_name;
Убираем из ''my.cnf''
port = 5678
innodb_force_recovery = 1
innodb_purge_threads = 0
и перезапускаем MySQL.
Восстанавливаем данные
Все базы
mysql < all_db.sql
Одну базу
mysql database_name < database_name.sql
Одну таблицу
mysql database_name < database_table.sql
Далее ради интереса можно запустить **mysqlchk**
mysqlcheck -–all-databases –repair
Да прибудет с вами RAID, UPS и бэкап. АдминЪ!
EOM
{{tag>linux mysql innodb}}