12

I am trying to restore a database in PMA but only have access to frm and ibd files - not the ib_log files which I understand you need.

I know I may not be able to recover the database data but is it possible to recover the structure of the tables from the frm files?

fraggley
  • 1,215
  • 2
  • 9
  • 19

6 Answers6

51

I restored the table from only .frm and .idb files.

Get the SQL query to create the tables

If you already know the schema of your tables, you can skip this step.

  1. First, install MySQL Utilities. Then you can use mysqlfrm command in command prompt (cmd).

  2. Second, get the SQL queries from .frm files using mysqlfrm command:

    mysqlfrm --diagnostic <path>/example_table.frm
    

Then you can get the SQL query to create same structured table. Like this:

CREATE TABLE `example_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(150) NOT NULL,
  `photo_url` varchar(150) NOT NULL,
  `password` varchar(600) NOT NULL,
  `active` smallint(6) NOT NULL,
  `plan` int(11) NOT NULL,
PRIMARY KEY `PRIMARY` (`id`)
) ENGINE=InnoDB;

Create the tables

Create the table(s) using the above SQL query.

If the old data still exists, you may have to drop the respective database and tables first. Make sure you have a backup of the data files.

Restore the data

Run this query to remove new table data:

ALTER TABLE example_table DISCARD TABLESPACE;

This removes connections between the new .frm file and the (new, empty) .idb file. Also, remove the .idb file in the folder.

Then, put the old .idb file into the new folder, e.g.:

cp backup/example_table.ibd <path>/example_table.idb

Make sure that the .ibd files can be read by the mysql user, e.g. by running chown -R mysql:mysql *.ibd in the folder.

Run this query to import old data:

ALTER TABLE example_table IMPORT TABLESPACE;

This imports data from the .idb file and will restore the data.

slhck
  • 36,575
  • 28
  • 148
  • 201
Jin Lin
  • 526
  • 5
  • 4
  • 1
    I tried this but I get the following error when I run import query "#1812 - Tablespace is missing for table `wallipop`.`categories`." – hysabone.com Nov 20 '18 at 14:20
  • 3
    I fixed that by changing ownership of file but now I'm getting "#1808 - Schema mismatch (Table has ROW_TYPE_DYNAMIC row format, .ibd file has ROW_TYPE_COMPACT row format)." – hysabone.com Nov 20 '18 at 14:28
  • 4
    For anyone else that comes's across the ROW_TYPE_DYNAMIC issue like I just did. You'll have to start the process over from beginning and on your create table statements add `ROW_FORMAT=COMPACT` after `ENGINE=InnoDB` so it looks like `) ENGINE=InnoDB ROW_FORMAT=COMPACT DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci` for example. Then repeat the steps like normal and it should work. – Jeff Wilbert Aug 23 '19 at 07:49
  • hey please guide me how to do permission/ownership step on windows? Make sure that the .ibd files can be read by the mysql user, e.g. by running chown -R mysql:mysql *.ibd in the folder. – Pervaiz Iqbal Sep 13 '19 at 10:09
  • If you have tons of .frm files ? – O.k Jun 20 '20 at 12:43
  • Are you sure it is idb files, not ibd ? – YudhiWidyatama Jun 21 '20 at 01:00
  • If I use `--server` instead of `--diagnostic` I get this error: _UnicodeDecodeError: 'ascii' codec can't decode byte 0xcf in position 6: ordinal not in range(128)_. Can I somehow solve this or I'm forced to use `--diagnostic` mode in this case? – JConstantine May 19 '21 at 06:53
  • @JeffWilbert After doing as you said I still cannot import the `.ibd`, but this time I get: _Schema mismatch (Clustered index validation failed. Because the .cfg file is missing, table definition of the IBD file could be different. Or the data file itself is already corrupted.)_ – JConstantine May 19 '21 at 08:45
  • It works for me !!! I try in wamp v3.... Thanks a lot ! – Jimit Shah Sep 03 '21 at 11:39
4

InnoDB needs the ib_log files for data recovery, but it also needs the ibdata1 file which contains the data dictionary and sometimes contains pending data for the tables.

The data dictionary is kind of a duplicate system that records table structure and also matches a table id to the physical .ibd file that contains the table data.

You can't just move .ibd files around without the InnoDB data dictionary, and the data dictionary must match the table id found inside the .ibd file. You can reattach a .ibd file and recover the data, but the procedure is not for the faint of heart. See http://www.chriscalender.com/recovering-an-innodb-table-from-only-an-ibd-file/

You can recover the structure using the .frm files with some file trickery, but you will not be able to create them as InnoDB tables at first. Here's a blog that covers a method for recovering .frm files as MyISAM tables: http://www.percona.com/blog/2008/12/17/recovering-create-table-statement-from-frm-file/

You won't be able to use PMA for this. You need superuser access to the data directory on the server.

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • 1
    I'd like to second Peter's way to recover the structure from .frm files. Just make sure MySQL version is lower than 5.6. 5.6 will complain the number of columns in the fake table is less than in frm file. – akuzminsky Nov 11 '14 at 19:09
2

You can recover table structure from .frm files and data from ibd files.

Using mysqlfrm tool which is part of MySQL Utilities

shell> mysqlfrm --diagnostic myfile.frm

Recreate the table in a database of the same name using table structure.

mysql> CREATE mytable (int i);

Discard the tablespace of the newly created table.

mysql> ALTER TABLE mytable DISCARD TABLESPACE;

Copy the orphan .idb file from your backup directory to the new database directory. Ensure that the .ibd file has the necessary file permissions.

Import the orphan .ibd file. A warning is issued indicating that InnoDB will attempt to import the file without schema verification.

mysql> ALTER TABLE r IMPORT TABLESPACE;SHOW WARNINGS;

igorsf
  • 382
  • 4
  • 13
2

After years i wanna join in the discussion to share my solution, founded yesterday when i met the same issue.

I searched and tried tons of different stuff (like use Mysql Utilities script), recreate the table and so on ... but the real solution was a bit more easy (and tricky) to do:

Step 1)

  • Backup old data folder (usually under mysql/data path)

Step 2)

  • Format or install somewhere else a fresh and clear mysql-server

Step 3)

  • Import from the backup (step 1) the folder(s) containing the frm/idb files in mysql/data

Note: ONLY the folders not all the files

Step 4)

  • Import from the backup (step 1) the file called ibdata1 and overwrite it in the fresh mysql installation

Step 5)

  • Restart the mysql server (this may ask some seconds before boot-up, just wait)

And that's all! Mysql server should boot-up normally after some seconds and if nothing is corrupted, files should be restored!

Little image to explain better: oldbackup

Explanation:

- Blue: files to import in the new mysql-server (step 3)

- Red: files to NOT import in the new mysql-server

- Green: ibdata1 file to import in the new mysql-server (step 4)

Zenek
  • 60
  • 2
  • 12
0

You can also try with mysql utility.

From book.frm file to a file book.sql:

mysqlfrm --server=root:mysqladmin@localhost:3306 D:\yahwehdb\yahweh_altera\book.frm > D:\yahwehdb\yahweh_altera\book.frm\book.sql --diagnostic --port=3307 --user=root

From a directory containing all .frm file to a file all.sql:

mysqlfrm --server=root:mysqladmin@localhost:3306 D:\yahwehdb\yahweh_altera > D:\yahwehdb\yahweh_altera\all.sql --diagnostic --port=3307 --user=root
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
-1

This is actually quite easy as long as you know how to do it, and no external software or shell commands are needed.

The database data is stored in C:\xampp\mysql\data\ or similar by default. The folders are the database tables. Inside each folder, the .frm file are the columns. The .ibd hold the row values.

First create the database(s) in PHPMyAdmin.

Get the SQL query generated from this site, under menu Recover structure > From .frm file:

https://recovery.twindb.com/

Upload each .frm file, and then copy and paste these queries into the SQL command to create the tables in PHPMyAdmin.

Then, on each table, do this SQL query:

ALTER TABLE table_name DISCARD TABLESPACE

This will automatically remove the new .ibd file from the database directory. Copy the old .ibd file into the database folder. Run the following command to activate the table again:

ALTER TABLE table_name IMPORT TABLESPACE

And that's it! You should be able to view and access all of your old values again.

Marcus Edensky
  • 924
  • 3
  • 13
  • 33