Падение MySQL с InnoDB почти всегда сводится к одной из двух историй: либо движок не успел корректно завершить транзакции, либо есть реальное повреждение страниц данных. В обоих случаях в центре внимания оказываются redo log (журнал повторного выполнения) и параметр innodb_force_recovery, который позволяет «завести» сервер в ограниченном режиме ради выгрузки данных.
Ниже — практичный сценарий для админа: как понять, что происходит, что нельзя делать в первые минуты, как аккуратно использовать innodb_force_recovery, и как снять mysqldump after crash, чтобы дальше восстанавливаться уже из логического дампа.
Как InnoDB поднимается после падения: crash recovery на пальцах
InnoDB хранит данные в tablespace (файлы ibdata* и/или *.ibd) и пишет изменения сначала в журнал redo log. По сути, redo — это «чек-лист», по которому InnoDB после аварии может довести данные до согласованного состояния.
Типовой сценарий нормальной аварийной раскрутки такой:
- MySQL стартует и InnoDB читает redo.
- Находит неприменённые изменения и докатывает их (roll-forward).
- Откатывает незавершённые транзакции (rollback), используя внутренние структуры (undo и т.д.).
Если redo целый и страницы данных читаются, сервер обычно поднимается сам. Если нет — в error log появляются ошибки чтения страниц, несоответствие контрольных сумм, падения на rollback и прочие симптомы, больше похожие на InnoDB corruption.
Файлы redo: ib_logfile и изменения в MySQL 8.0
Термин ib_logfile0/ib_logfile1 часто встречается в старых инструкциях, но в MySQL 8.0 redo устроен иначе.
- MySQL 5.7 и ниже: redo — файлы
ib_logfile0,ib_logfile1(размер задаётсяinnodb_log_file_size, количество —innodb_log_files_in_group). - MySQL 8.0: вместо «старых»
ib_logfile*обычно используется каталог#innodb_redo, а ёмкость задаётсяinnodb_redo_log_capacity.
Практический вывод: советы вида «удалите ib_logfile0» применимы только к старым версиям и далеко не всегда безопасны. При аварии ваша цель — сначала снять данные (логический дамп), а не «чинить» tablespace грубой силой.
Первый час после падения: что делать и чего не делать
Когда MySQL перестал стартовать или падает на recovery, самая частая ошибка — хаотично менять файлы в datadir. Действуйте по чек-листу: сначала фиксация симптомов и копия, потом эксперименты.
1) Зафиксируйте симптомы по error log и состоянию диска
Нужно быстро ответить на вопрос: это обычный crash recovery или уже повреждение.
- Сохраните error log MySQL (хотя бы последние 2000 строк).
- Посмотрите, на каком этапе падает: «Starting crash recovery», «Rolling back trx», «page corruption», «Assertion failure», SIGSEGV.
- Проверьте базовые причины:
No space left, I/O errors, read-only FS, проблемы питания/виртуализации.
Если давно не тюнили дисковые операции InnoDB, отдельно полезно посмотреть, не усугубляет ли ситуацию перегруженный буфер и I/O: практика тюнинга buffer pool и дискового I/O в InnoDB.
2) Остановите MySQL и сделайте копию datadir (или снапшот диска)
Это обязательный шаг, даже если у вас есть бэкап. Одна неверная попытка «починки» может ухудшить ситуацию. Копия нужна, чтобы откатываться и пробовать разные стратегии без дополнительных потерь.
systemctl stop mysql
mkdir -p /root/mysql-datadir-copy
rsync -aH --numeric-ids /var/lib/mysql/ /root/mysql-datadir-copy/
Если MySQL управляется иначе (например, сервис называется mariadb), останавливайте соответствующий юнит.
3) Не удаляйте redo «наугад»
Удаление redo-файлов иногда заставляет сервер стартовать, но ценой потери данных и согласованности. Если цель — спасти максимум, сначала добейтесь режима чтения и сделайте дамп.
Трогать redo осмысленно только на копии данных и когда вы точно понимаете версию MySQL, формат redo и последствия конкретного действия. В боевом datadir это почти всегда лишний риск.
Если база критична, а вокруг нет ресурсов под «спасение» (CPU/RAM/IO), часто проще и безопаснее поднять временный экземпляр на отдельном VDS и работать с копией datadir там, не мешая продакшен-серверу и не усугубляя проблему на исходном диске.

Когда нужен innodb_force_recovery и что он реально делает
innodb_force_recovery — аварийный флаг, который отключает части механизма восстановления InnoDB. Он нужен, когда обычный InnoDB crash recovery не завершается и сервер падает. Цель режима — дать шанс прочитать как можно больше данных и выгрузить их.
Важно: это не лечение. Это режим «реанимации ради эвакуации».
Уровни innodb_force_recovery (1–6): как выбирать
Тактика простая: начинайте с минимального значения и повышайте только если MySQL всё ещё не стартует. Чем выше уровень, тем больше ограничений и тем выше риск неконсистентных данных (потому что InnoDB меньше делает откатов/фоновой обработки).
- 1 — наиболее мягкий режим: часть проверок/операций упрощается.
- 2 — чаще помогает при проблемах с purge/фоновой обработкой.
- 3 — ещё меньше фоновой активности; часто уже достаточно для чтения и дампа.
- 4 — отключает механики, связанные с insert/change buffer (может помочь при повреждениях страниц).
- 5 — ограничивает работу с undo/rollback; данные могут остаться «как есть» после падения.
- 6 — максимально ограниченный режим, когда попытки полноценного восстановления почти выключены; иногда единственный шанс снять дамп.
Формулировки и детали слегка отличаются между версиями, но практический подход одинаковый: 1 → 2 → 3 → 4 → 5 → 6, останавливаясь на первом значении, при котором сервер стабильно поднимается и даёт читать нужные таблицы.
Как включить innodb_force_recovery правильно
Добавьте параметр в конфигурацию MySQL (обычно /etc/mysql/my.cnf или файл в /etc/mysql/conf.d/; на некоторых системах — /etc/my.cnf).
systemctl stop mysql
printf '%s
' '[mysqld]' 'innodb_force_recovery=1' > /etc/mysql/conf.d/innodb-recovery.cnf
systemctl start mysql
systemctl status mysql
Если не стартует — увеличьте значение, но делайте это только после остановки сервиса и по одному шагу.
systemctl stop mysql
sed -i 's/innodb_force_recovery=1/innodb_force_recovery=2/' /etc/mysql/conf.d/innodb-recovery.cnf
systemctl start mysql
При включённом innodb_force_recovery любые записи в InnoDB потенциально опасны. Ваша цель — поднять сервер и читать достаточно долго, чтобы выгрузить данные.
Как снять mysqldump после crash: рабочая последовательность
Когда сервер поднялся в режиме recovery, действуйте как при «инциденте только на чтение»: минимум нагрузки, максимум предсказуемости, быстрый вывоз данных.
1) Отключите запись приложению
Идеально — остановить приложение или перевести в maintenance. Если это невозможно, временно запретите запись на уровне MySQL-аккаунтов приложения (REVOKE) или ограничьте доступ до БД на уровне сети.
Не рассчитывайте на «само пройдёт»: при некоторых уровнях innodb_force_recovery попытка записи может ускорить деградацию и сделать чтение ещё хуже.
2) Дамп снимайте порционно и с предсказуемыми флагами
Если данных много, идите по базам: сначала системно важные, затем крупные. Дамп лучше писать в отдельный каталог и сразу проверять, что файл растёт.
mysql -e 'SHOW DATABASES'
mysqldump --single-transaction --routines --events --triggers --databases your_db > /root/your_db.sql
Если --single-transaction ругается или дамп становится нестабильным (такое бывает при тяжёлой corruption) — попробуйте без него, но учитывайте риск неконсистентности. Часто помогает стратегия «по таблицам», чтобы быстро пропускать проблемные места.
3) Если дамп падает на конкретной таблице
Типичная картина при InnoDB corruption: чтение конкретных страниц вызывает ошибку и рвёт соединение. Тогда спасаем максимум и локализуем проблему.
- Дампите базу по таблицам, фиксируя на какой таблице ломается.
- Исключите проблемную таблицу и сохраните всё остальное.
- Для проблемной таблицы пробуйте читать по частям (например, по диапазону PK), если чтение хоть частично возможно.
mysqldump --single-transaction --skip-triggers your_db good_table > /root/good_table.sql
mysqldump --single-transaction --skip-triggers your_db bad_table > /root/bad_table.sql
Если на bad_table стабильно падает — отложите её и продолжайте «эвакуацию» остального. На практике «минус одна таблица» лучше, чем «минус вся база».
4) Быстро проверьте, что дамп не пустой и похож на рабочий
Минимальная проверка — что файл не пустой и содержит ожидаемые DDL/DML. Более правильная — импортировать дамп в отдельный чистый экземпляр и прогнать базовые запросы (хотя бы по ключевым таблицам).
grep -n 'CREATE TABLE' /root/your_db.sql | head
grep -n 'INSERT INTO' /root/your_db.sql | head
Если вы хотите восстановиться «до точки во времени» после последнего полного дампа, пригодятся binlog/GTID. Это отдельная тема: PITR в MySQL/MariaDB через binlog и GTID.

Что делать после эвакуации: вернуться в строй на чистой базе
После того как вы сняли логический дамп, правильный следующий шаг — развернуть чистый экземпляр и загрузить данные туда. Не пытайтесь превращать аварийный экземпляр в прод: если было повреждение, оно может проявляться снова.
Базовая схема восстановления
- Поднимите новый
datadir(инициализация). - Запустите MySQL без
innodb_force_recovery. - Импортируйте дамп.
- Проверьте приложение и целостность данных.
Если вы работаете на том же сервере, часто проще остановить MySQL, перенести старый datadir в сторону, создать новый и импортировать.
systemctl stop mysql
mv /var/lib/mysql /var/lib/mysql.broken
mkdir -p /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
mysqld --initialize-insecure --user=mysql
systemctl start mysql
Команда инициализации зависит от дистрибутива/пакета; где-то вместо этого используется mysql_install_db. Смысл один: создать новый «чистый» InnoDB и восстановиться логически.
Про попытки «починки» старого datadir и redo
Иногда хочется «просто заставить стартовать» старую директорию с данными: менять размер redo, переименовывать/удалять redo, пересоздавать файлы и т.п. Как диагностика на копии — допустимо. Как стратегия восстановления — плохая:
- Можно потерять последние подтверждённые транзакции (которые были только в redo).
- Можно получить скрытую логическую порчу, которая вылезет позже.
- Если причина в диске/контроллере/ФС, проблема повторится.
Надёжная цель — получить логический дамп и переехать на чистую инсталляцию.
Как отличить «обычный crash» от реальной InnoDB corruption
Признаки, что дело не только в незавершённом recovery, а в повреждениях:
- В error log явно упоминаются checksum mismatch, page corruption, «database page corruption», «cannot find record in index».
- MySQL падает на одном и том же месте даже при повторном старте.
- Проблема привязана к конкретной таблице/индексу: любой SELECT из неё валит сервер или рвёт соединение.
- Есть I/O ошибки на уровне ОС (системные логи), read errors, проблемы с файловой системой.
Если это corruption, innodb_force_recovery почти всегда часть сценария спасения: стандартный rollback/recovery может быть невозможен.
Профилактика: что настроить, чтобы аварии переживать проще
Полностью исключить падения нельзя, но можно сделать восстановление рутинной процедурой, а не лотереей.
1) Регулярные бэкапы и тест восстановления
Бэкап без проверки восстановления — это гипотеза. Минимум: периодически поднимать тестовый MySQL и импортировать дамп или восстанавливать физический бэкап.
Если бэкапы ещё не автоматизированы и вы храните их вне сервера, пригодится схема с S3-совместимым хранилищем: бэкапы в S3 через restic/borg.
2) Мониторинг диска и ошибок ввода-вывода
Многие случаи InnoDB corruption начинаются с проблем хранения: ошибки чтения, подвисания диска, внезапные read-only перемонтирования. Мониторьте свободное место, задержки I/O и сообщения ядра/ФС в системных логах.
3) Запас по ресурсам и изоляция окружений
Crash recovery и дампы после аварии требуют CPU/RAM/IO. Если сервер постоянно работает на пределе, rollback может занимать часы. Планируйте запас, а для критичных проектов держите отдельную среду, где можно проверять восстановление.
Короткий плейбук на случай инцидента
- Остановить MySQL.
- Сделать копию
datadir(или снапшот диска). - Запустить с
innodb_force_recovery=1и повышать до старта (максимум до 6). - Отключить запись приложению.
- Снять mysqldump after crash (по базам/таблицам, спасая максимум).
- Развернуть чистый MySQL и импортировать дамп.
- Убрать
innodb_force_recoveryи не возвращать прод на «поломанном»datadir.
Главная мысль: redo log создан, чтобы переживать падения, но если InnoDB не поднимается, ваша задача — не чинить любой ценой, а быстро перевести сервер в режим чтения, выгрузить данные и восстановиться на чистой базе.


