MariaDB/MySQL — Restore Database From .frm And .ibd Files

Badal Naik
2 min readFeb 17, 2019

--

A very fine morning, you came to know your production database is down.

And you login to mysql and fire select * on random table and mysql Says:

Table Doesn’t exists in database

And then you dig it deeper and get to know your ibdata files are corrupted!

But wait! You have enabled innodb_file_per_table configuration in your mysql!

Let’s get the data back! (Its already there we just need to recreate table space).

Install mysqlfrm and mysql-client (if its already not installed) in a same instance where your mysql is.

sudo apt-get install mysql-utilities mysql-client

Now create a restore database,

mysql -uroot -e “create database restored_mydatabase

Now Lets say you want to restore data of database named “mydatabase”

Step-1:

Get the table schema of mydatabase:

mysqlfrm /var/lib/mysql/mydatabase/*.frm — server=root@localhost — port 3308 — user mysql > mydatabase_schema.sql

Now we need to put semicolon in schema file!

sed -i ‘s/^$/;/’ mydatabase_schema.sql

Change the database name in schema:

sed -i ‘s/mydatabase/restored_mydatabase/g’ mydatabase_schema.sql

Now lets create schema of mydatabase into restored_mydatabase:

mysql -D restored_mydatabase < mydatabase_schema.sql — force

Now we have .frm files created for restored_mydatabase.

Now lets create SQL statements for discarding tablespace for all tables:

mysql -N -B <<’EOF’ > discard-ddl.sqlSELECT CONCAT(‘ALTER TABLE `’, table_name, ‘` DISCARD TABLESPACE;’) AS _ddlFROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=’restored_mydatabase’ AND ENGINE=’InnoDB’;EOF

Now discarding table space!

mysql -D restored_mydatabase < discard-ddl.sql — force

Now copy all idb files for mydatabase directory to restored_mydatabase directory:

cp /var/lib/mysql/mydatabase/*.ibd /var/lib/mysql/restored_mydatabase/

Change ownership to mysql :

chown -R mysql:mysql /var/lib/mysql/restored_mydatabase/

And now yout restored_database has your old data back but wait! it doesn’t have it in table space!

Create statements for importing tablespace with your data!

mysql -N -B <<'EOF' > import-ddl.sqlSELECT CONCAT('ALTER TABLE `', table_name, '` IMPORT TABLESPACE;') AS _ddlFROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=‘restored_mydatabase’ AND ENGINE='InnoDB';EOF

Now Import tablespace:

mysql -D restored_mydatabase < import-ddl.sql — force

Login to mysql and check if you got your data:

mysql -urootuse restored_mydatabaseselect * from table

Now take dump of restored_database and restore to original one:


mysqldump -uroot restored_mydatabase > restored_mydatabase.sql
mysql -uroot -e "DROP DATABASE mydatabase"mysql -uroot -e "CREATE DATABASE mydatabase"mysql -uroot -D mydatabase < restored_mydatabase.sql

That’s it!

References:

--

--

Badal Naik

Questioning. Argumentative. Listening. Learning. Thinking. Believe In Action. Linux/Kubernetes Enthusiast.