Как бы не убеждал нас Oracle и Mariadb о надежности InnoDB - это не так.
Поддержка транзакций и прочее страшные слова хороши до тех пор пока база данных не скрашилась (как вариант, не была дерзко скопирована в другое место). В этом случае наступает кризис, и останавливается работа.
Итак, описанный хак будет работать только в случае, если вы используете хранение каждой таблицы в отдельном файле (параметр innodb_file_per_table=1 в my.cnf). Если у вас такой настройки нет - сделайте ее, иначе будет поздно. Вы можете определить использование отдельного файла для таблицы, по присутствию множества .ibd файлов в каталоге базы данных.
Т.е., примерно в /var/lib/mysql/DATABASE_NAME/ у вас должны быть файлы с расширением FRM и IBD.
FRM - это структура таблицы. IBD - содержимое таблицы. Простое копирование не поможет, поскольку несмотря на то, что MySQL будет видеть названия таблиц, ни SELECT FROM ни DESC не получится.
Итак, допустим у вас есть все условия: бэкап с множеством IBD-файлов:
1) Удаляем файлы ibdata1 и логи в папке /var/lib/mysql (или в вашем каталоге с базами)
2) Перезапускаем MySQL. Он должен перезапуститься
3) Открываем консоль MySQL и заходим в него
4) Выполняем show databases; use <имя_вашей_базы>;show tables - вы должны увидеть таблицы.
Основной принцип восстановления таблиц из файлов следующий:
1) Создаем промежуточную базу данных
2) Восстанавливаем структуру каждой таблицы вашей поврежденной базы, при помощи утилиты
3) Создаем таблицы в промежуточной базе, на основе восстановленных из предыдущего пункта
4) Удаляем текущий контент таблицы, при помощи хитрой команды
5) Копируем физический файл с данными таблицы, из нашей поврежденной базы
6) Заставляем MySQL принять и перечитать новые данные.
Как это будет в командах.
1) cd /var/lib/mysql
2) rm ib_logfile0;rm ib_logfile1; rm ibdata1
3) service mysql restart
4) mysql -u'root' -p'ваш_пароль'
5) CREATE DATABASE swap;
6) quit
7) mysqlfrm --server=root:ваш_пароль@localhost:3306 --diagnostic <имя_файла.frm> > table.sql
8) mysql -u'root' -p'ваш_пароль' swap < table.sql
9) Предыдущие команды возможно вызовут ошибки, они незначительные, к примеру незакомментированное слово WARNING, но их придется устранить вручную
10) mysql -u'root' -p'ваш_пароль' swap
11) ALTER TABLE <имя_таблицы_которую мы создали пару пунктов назад> DISCARD TABLESPACE;
12) quit
13) cp <файл_таблицы.ibd из поврежденной базы> swap/ - попросту говоря, копируем восстанавливаемый файл IBD из папки старой базы, в папку с новой
14) mysql -u'root' -p'ваш_пароль' swap
15) ALTER TABLE <имя_таблицы_которую мы создали пару пунктов назад> IMPORT TABLESPACE;
16) Вуаля. service mysql restart
Для автоматизации рутинной работы, я написал скрипт
Код скрипта:
#!/bin/bash
pass='ваш_рутовый_пароль_на_mysql'
rm swapchmod 777 $tbl.ibd
echo "OK"
done
Скрипт должен быть размещен в каталоге datadir (/var/lib/mysql)
Запускается он, находясь в каталоге, командой ./script.sh <имя_базы_данных>
Естественно, каталог с базой должен находиться здесь же. Скрипт создаст новую базу с таким же названием, но со знаком подчеркивания. Не забудьте так же поставить mysqlfrm (apt-get install mysql-utilities в Debian-based).
Не упрекайте меня пожалуйста за красоту программирования на bash, главная цель вовсе не она.
Надеюсь я вам помог.