A MySQL/MariaDB DBA/Consultant/Trainer with Expertise in Database Designing, Development, Maintenance, Installation, Upgradation, Configuration optimization, Setting and Managing Replication, Backup and Restore,Cross Database Migration, Optimization, Synchronization of replicated database, Performance and Monitoring, High Availability
Sunday, August 12, 2012
MySQL: How to recover Recovery deleted ibdata1
A interesting Article to read
Recently I had a case when a customer deleted the InnoDB main table space – ibdata1 – and redo logs – ib_logfile*.
MySQL keeps InnoDB files open all the time. The following recovery technique is based on this fact and it allowed to salvage the database.
Actually, the files were deleted long time ago – 6 months or so. As long as file is open physically it still exits in the file system and reachable to processes which have opened it.
Thus, from user perspective nothing has changed after the deletion. By the way, this is a good reason to monitor existence of these files! But after the restart InnoDB will detect that there is neither system table space nor log files, so it will create empty ones. The InnoDB dictionary will be empty and InnoDB won’t be able to use a bunch of existing ibd files. This situation will be a job for ibdconnect, but as long as MySQL isn’t restarted it is possible to recover database fast. Let me illustrate how.
Let’s simulate the accident. For that I will delete /var/lib/mysql/ib* files, while sysbench generates read/write activity:
root@localhost:~# sysbench --num-threads=16 --max-requests=0 --test=oltp --oltp-table-size=1000000 --max-time=3600 --mysql-user=root run
sysbench 0.4.12: multi-threaded system evaluation benchmark
No DB drivers specified, using mysql
Running the test with following options:
Number of threads: 16
Doing OLTP test.
Running mixed OLTP test
Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
However, we can’t copy them back because at any given point of time, there are modified pages in the buffer pool. Those pages are not written on disk and will be lost if the changes are not permanently written. This can lead to corruption and data loss.
For the same reason we can’t make MySQL backup by just copying the files.
So, we have to make sure all modifications are written to the disk.
For that we have to stop any further writes and wait until InnoDB flushes all pages.
To stop write activity we can either stop application or lock tables:
Now let’s wait until all dirty pages are flushed on disk. For that we will monitor checkpoint age. The checkpoint age is a difference between current log sequence number and last checkpoint in “SHOW ENGINE INNODB STATUS” output. If checkpoint age is zero, all pages are flushed:
Log sequence number 363096003
Log flushed up to 363096003
Last checkpoint at 363096003
Max checkpoint age 7782360
To speed up flushing we can set dirty pages percentage to zero:
mysql> set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected (0.01 sec)
It is also important to ensure all other background processes have finished their work. One of them is the insert buffer thread. Its size should be not more than 1(it’s never less than 1):
INSERT BUFFER AND ADAPTIVE HASH INDEX
Ibuf: size 1, free list len 398, seg size 400,
Another thread writing in background is the purge thread. It should purge all transactions up to very last
Trx id counter 0 16644
Purge done for trx's n:o < 0 16644 undo n:o < 0 0
But if the last transaction wasn’t something that requires a purge operation (SELECT for example) Trx id counter will be bigger. In that case at least ensure InnoDB isn’t doing any writes: