ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

MySQL InnoDB: redo log и innodb_force_recovery после падения

Пошаговый плейбук InnoDB crash recovery: как читать симптомы по error log, почему нельзя трогать redo наугад, как по уровням включать innodb_force_recovery и снять mysqldump даже при corruption, чтобы восстановиться на чистом datadir.
MySQL InnoDB: redo log и innodb_force_recovery после падения

Падение 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 там, не мешая продакшен-серверу и не усугубляя проблему на исходном диске.

Фрагмент error log MySQL с сообщениями InnoDB crash recovery и ошибками чтения страниц

Когда нужен innodb_force_recovery и что он реально делает

innodb_force_recovery — аварийный флаг, который отключает части механизма восстановления InnoDB. Он нужен, когда обычный InnoDB crash recovery не завершается и сервер падает. Цель режима — дать шанс прочитать как можно больше данных и выгрузить их.

Важно: это не лечение. Это режим «реанимации ради эвакуации».

Уровни innodb_force_recovery (1–6): как выбирать

Тактика простая: начинайте с минимального значения и повышайте только если MySQL всё ещё не стартует. Чем выше уровень, тем больше ограничений и тем выше риск неконсистентных данных (потому что InnoDB меньше делает откатов/фоновой обработки).

  1. 1 — наиболее мягкий режим: часть проверок/операций упрощается.
  2. 2 — чаще помогает при проблемах с purge/фоновой обработкой.
  3. 3 — ещё меньше фоновой активности; часто уже достаточно для чтения и дампа.
  4. 4 — отключает механики, связанные с insert/change buffer (может помочь при повреждениях страниц).
  5. 5 — ограничивает работу с undo/rollback; данные могут остаться «как есть» после падения.
  6. 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 потенциально опасны. Ваша цель — поднять сервер и читать достаточно долго, чтобы выгрузить данные.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Как снять 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.

Запуск mysqldump в терминале и список полученных SQL-дампов для восстановления

Что делать после эвакуации: вернуться в строй на чистой базе

После того как вы сняли логический дамп, правильный следующий шаг — развернуть чистый экземпляр и загрузить данные туда. Не пытайтесь превращать аварийный экземпляр в прод: если было повреждение, оно может проявляться снова.

Базовая схема восстановления

  • Поднимите новый 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).
  • Можно получить скрытую логическую порчу, которая вылезет позже.
  • Если причина в диске/контроллере/ФС, проблема повторится.

Надёжная цель — получить логический дамп и переехать на чистую инсталляцию.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Как отличить «обычный 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 может занимать часы. Планируйте запас, а для критичных проектов держите отдельную среду, где можно проверять восстановление.

Короткий плейбук на случай инцидента

  1. Остановить MySQL.
  2. Сделать копию datadir (или снапшот диска).
  3. Запустить с innodb_force_recovery=1 и повышать до старта (максимум до 6).
  4. Отключить запись приложению.
  5. Снять mysqldump after crash (по базам/таблицам, спасая максимум).
  6. Развернуть чистый MySQL и импортировать дамп.
  7. Убрать innodb_force_recovery и не возвращать прод на «поломанном» datadir.

Главная мысль: redo log создан, чтобы переживать падения, но если InnoDB не поднимается, ваша задача — не чинить любой ценой, а быстро перевести сервер в режим чтения, выгрузить данные и восстановиться на чистой базе.

Поделиться статьей

Вам будет интересно

PostgreSQL pg_hba.conf: настройка аутентификации и разбор типовых ошибок OpenAI Статья написана AI (GPT 5)

PostgreSQL pg_hba.conf: настройка аутентификации и разбор типовых ошибок

Разбираем pg_hba.conf в PostgreSQL: как читаются правила сверху вниз, чем отличаются peer, md5 и scram-sha-256, как безопасно откр ...
Postfix + Dovecot: как разбирать ошибки 552 и 554 и настраивать лимиты без боли OpenAI Статья написана AI (GPT 5)

Postfix + Dovecot: как разбирать ошибки 552 и 554 и настраивать лимиты без боли

Ошибки 552 и 554 в связке Postfix+Dovecot почти всегда связаны с лимитами или политиками: размер письма, квоты, число соединений, ...
SPF: include, redirect, ip4/ip6 и all — как собрать запись без PermError и лимита lookups OpenAI Статья написана AI (GPT 5)

SPF: include, redirect, ip4/ip6 и all — как собрать запись без PermError и лимита lookups

SPF-запись помогает почтовым серверам понять, какие источники могут отправлять письма от имени домена. Разберём include и redirect ...