Восстановление InnoDB базы из файловой копии (.ibd и .frm)

Иногда возникает необходимость восстановить всю InnoDB базу или какие-то конкретные таблицы, а дампа нет, есть только файлы .ibd и .frm, которые обычно лежат в папке /var/lib/mysql/имя-вашей-базы . Просто копированием в InnoDB эта проблема не решается. Метод, указанный ниже подходит, если у вас есть файловый бэкап для каждой таблицы. Если вся база хранилась в одном файле - то сложно будет что-то с этим сделать. Итак, создаем пустую базу:

    CREATE DATABASE recovery;
    USE recovery;

Далее следует создать таблицу, которую восстанавливаем, полностью сохранив её структуру. Если структура неизвестна - можно сделать следущее: Создадим таблицу с тем же именем, но произвольной структурой, например: CREATE TABLE test(table_id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ( table_id )); Затем возьмем .frm от оригинальной таблицы и заменим его на .frm свежесозданной. Потом сделаем:

    SHOW CREATE TABLE test;

И увидим оригинальную структуру. Удаляем таблицу которую мы создали и создаем таблицу с уже известной оригинальной структурой. Создаются два файла .frm и .ibd Избавляемся от созданного .ibd с помощью:

    ALTER TABLE test DISCARD TABLESPACE;

Копируем на его место оригинальный .ibd файл и делаем:

    ALTER TABLE test IMPORT TABLESPACE;

Если импорт прошел удачно - то перезапускайте mysql с ключом innodb_force_recovery от 1 до 6 (мне помогло значение 5), и как только содержимое таблицы увидится - делайте дамп этой таблицы. Зачастую импорт не получается так, и мы видим ошибку ERROR 1030 (HY000): Got error -1 from storage engine

Это значит надо пойти в лог mysql и увидеть ошибку вида: InnoDB: Error: tablespace id in file '.test.ibd' is 472, but in the InnoDB data dictionary it is 1. Это значит что айди оригинальной таблицы 472, а у нас он пока равен 1. чтобы это исправить надо удалить таблицу, сгенерировать нехватающее количество произвольных таблиц, удалить их и создать еще раз нужную по предыдущей схеме. и тогда она импортируется. В создании и удалении большого кол-ва таблиц поможет php скрипт:

    


        $dbhost = "localhost";
        $dbname = dbname;
        $dbuser = login;
        $dbpwd  = password;
        $counter = how much;

        mysql_connect($dbhost,$dbuser,$dbpwd) or die(mysql_error());

        for ($i = 1; $i <=$counter; $i++) {
            $dbquery = "CREATE TABLE " . $dbname . ".t" . $i . " (id int) ENGINE=InnoDB";
            //$dbquery = "DROP TABLE " . $dbname . ".t" . $i ;
            echo "" . $dbquery . "";

            $result = mysql_db_query($dbname,$dbquery) or die(mysql_error());

            $j = 0;

            while($row = mysql_fetch_array($result)) {
                $j++;
                echo $row[0];
            }
        }

        mysql_close();


Если же у вас наоборот айди текущей таблицы превысил нужный из .ibd то можно удалить базу, удалить файлы ib_logfile0, ib_logfile1, ibdata1 и перезапустить mysql. Тогда вновь созданая таблица во вновь созданной базе будете иметь айди равный единице. Осторожно отнеситесь к этому методу, если у вас на той машине, где вы все это производите крутятся другие базы. Делайте бэкапы всего что можно, дампы и т.д.

{{ message }}

{{ 'Comments are closed.' | trans }}