2

Last night, my MySQL server crashed and now I have several databases, which data I'm unable to recover.

According to errorlog, the coruptions in tablespaces happend quite a while ago (few months), but no one notticed that and yesterday, when MySQL crashed (for completely different reason), it just failed to start with following error:

2015-06-09 23:09:23 14642 [Note] InnoDB: Starting crash recovery. 2015-06-09 23:09:23 14642 [Note] InnoDB: Reading tablespace information from the .ibd files... 2015-06-09 23:09:24 14642 [ERROR] InnoDB: Tried to read 16384 bytes at offset 0. Was only able to read 0. 2015-06-09 23:09:24 7f648369a7e0 InnoDB: Operating system error number 2 in a file operation. InnoDB: The error means the system cannot find the path specified. InnoDB: If you are installing InnoDB, remember that you must create InnoDB: directories yourself, InnoDB does not create them. 2015-06-09 23:09:24 14642 [ERROR] InnoDB: File (unknown): 'read' returned OS error 71. Cannot continue operation 

When the db was started with innodb-force-recovery set to 6, server started, with tons of those messages in error log:

2015-06-09 23:16:50 16659 [ERROR] InnoDB: Failed to find tablespace for table '"db1234"."tbl456"' in the cache. Attempting to load the tablespace with space id 275772. 

I managed to dump majority of databases and import them to clean data directory. But some dbs have corrupted tablespace and I can't dump them (or even open any table in them).

So now i have several (about a hundred) databases, which can't be loaded into live MySQL server. I have their data files (both .frm and .ibd files) but they are somehow corrupted and MySQL can't open them:

2015-06-10 18:37:18 3965 [Warning] InnoDB: Cannot open table db123/tbl456 from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how you can resolve the problem. 

I tried to copy data files into another MySQL instance, but with no success, i even tried to create fresh .frm files (but i don't know the structure of the tables), stop the server, replace them with the right ones, start the server and open them - again with no success.

Sadly, i don't have backup of those databases, because they were corrupted long time ago and the backup dumps failed to save any data.

So now i have the data in innodb data files but can't load them into live server. Is there any way how to save them?

I found this toolkit: https://www.percona.com/software/mysql-innodb-data-recovery-tools, but i'm not sure if it is possible for me to use it, its quite complicated and i dont see how to recover a hundred of databases, which structure is unknown to me..

Server uses MySQL 5.6.17, compiled from source.

2 Answers 2

2

As the author of Percona data recovery toolkit I recommend you to use TwinDB data recovery toolkit. There is no development in Percona's toolkit last two years and all new features go to TwinDB's toolkit. You case is described in a post Recover Corrupt MySQL Database

To recover table structure you can use mysqlfrm tool or recover the structure from InnoDB dictionary

1
  • Thank you for your reply. That is exactly what i was loking for.. though i managed to retrieve all important data from database without digging from datafiles (so i didnt realy use the toolkit). But still, thank you for it .. i'll definetly find it useful in the future. Commented Jun 15, 2015 at 14:11
0

Have been struggling with a broken MySQL/MariaDB database for days and finally found something that works, based on this tutorial. In my case, I saw errors like:

#1932 - Table 'phpmyadmin.pma__recent' doesn't exist in engine ERROR 1030 (HY000): Got error 194 "Tablespace is missing for a table" from storage engine InnoDB ERROR 1146 (42S02): Table 'my_database.my_table' doesn't exist ERROR 1813 (HY000): Tablespace for table '`my_database`.`my_table`' exists. Please DISCARD the tablespace before IMPORT 

Disclaimer: The solution described below seems rather risky to me, but unfortunately I had no current SQL dump backups (I will make more often in the future and recommend this to you too!). I see it more as a “last resort”. If you have a recent SQL dump, it might be worth using it instead.

Assumptions:

  • You have root access via sudo.
  • Your MySQL server is running.
  • Your MySQL/MariaDB database directory is in /var/lib/mysql.
  • Your MySQLuser name is mysql.
  • You backed up ALL files in your MySQL database directory in case you mess up. (We will drop tables in the following!)
  • You have a temporary working directory into which the mysql user can copy files (I will use /home/mysql/tmp_bck in the following).
  • You set innodb_force_recovery=0 in your MySQL configuration (/etc/mysql/my.cnf) or it is not set/changed at all (otherwise you can't write).
  • You have the mysqlfrm tool installed. If you don't have it yet, install it with sudo apt-get install mysql-utilities.

Make sure the things above are fulfilled before continuing.

For each database that we want to recover, create a temporary working directory. Let's assume the database is called my_database, then execute:

sudo -u mysql mkdir /home/mysql/tmp_bck/my_database 

For each table (e.g. my_table) in this database that we want to recover:

  1. In your bash/SSH console, create a temporary backup of the database structure/format (.frm) and data (.ibd). Then use mysqlfrm to log in to your MySQL server (here: with the user "root", password "my_password" (replace), and port 3306 (default)) and crate a temporary dummy server on another port (here: 3310).
sudo -u mysql cp /var/lib/mysql/my_database/my_table.frm /home/mysql/tmp_bck/my_database/my_table.frm sudo -u mysql cp /var/lib/mysql/my_database/my_table.ibd /home/mysql/tmp_bck/my_database/my_table.ibd cd /var/lib/mysql/my_database sudo -u mysql mysqlfrm --server=root:my_password@localhost:3306 my_table.frm --port=3310 

mysqlfrm will give you a CREATE TABLE command, for example:

CREATE TABLE `wp_options` ( `option_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `option_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `option_value` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `autoload` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'yes', PRIMARY KEY (`option_id`), UNIQUE KEY `option_name` (`option_name`), KEY `autoload` (`autoload`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 

Copy this , add a ; at the end, and keep it for step 4!

  1. In your MySQl command line (start a second bash/SSH window and run mysql -u root -p), select your database and drop/delete the table. This will result in data loss if you didn't do a backup of the .frm/.ibd files before starting or if the above copying failed!:
USE my_database; DROP TABLE my_table; 
  1. Back in your regular bash, stop the server, delete any remaining .frm/.ibd file (at least the .ibd file was still present in my case), and restart the server:
sudo systemctl stop mariadb sudo -u mysql rm /var/lib/mysql/my_database/my_table.frm sudo -u mysql rm /var/lib/mysql/my_database/my_table.ibd sudo systemctl start mariadb 
  1. In your MySQl command line, create the table with the CREATE TABLE command from step 1, for example:
CREATE TABLE `wp_options` ( `option_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `option_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `option_value` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `autoload` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'yes', PRIMARY KEY (`option_id`), UNIQUE KEY `option_name` (`option_name`), KEY `autoload` (`autoload`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

Then, delete the .ibd data tablespace with:

ALTER TABLE my_table DISCARD TABLESPACE; 
  1. Back in your regular bash, copy the .ibd file from your temporary backup:
sudo -u mysql cp -f /home/mysql/tmp_bck/my_database/my_table.ibd /var/lib/mysql/my_database/my_table.ibd sudo chmod 660 /var/lib/mysql/my_database/my_table.ibd 
  1. Finally, in MySQL, import the .ibd file that was just copied from the backup:
ALTER TABLE my_table IMPORT TABLESPACE; 

Done! Make sure this succeeds (e.g., using phpmyadmin, you shouldn't see an error message but instead see a table with data, or at least an empty table without an error message). Repeat the steps above for each database/table. Good luck!

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.