MySQL误删ibdata1 ib_logfile0,ib_logfile1 恢复方法:
恢复的步骤和数据库版本没有太大关系。
在linux操作系统中,如果文件从操作系统级别别rm掉,之前打开的文件进程仍持有相应的文件句柄,
所指向的文件仍然可以读写,且该文件的描述符可以从/proc目录中获得(不关闭MySQLd情况下).
在删除3个文件后,MySQLd 仍是可以运行,对外服务的,MySQL一只保持InnoDB文件打开,因此,
在工作中有必要监控文件是否存在。
发现文件被删除之后,不能重启InnoDB,因为启动InnoDB,检测到ibdata1,ib_logfile0,ib_logfile1
不存在,所以,将创建对应的空文件,InnoDB数据字典是空的,InnoDB无法使用原先存在的ibd文件,故,
MySQL不重启,快速恢复删除的文件是可能的。
在MySQLd运行过程中,ibdata1,ib_logfile0,ib_logfile1一直运行在
/proc/vm-mysql.pid/fd目录下,其中vm-mysql.pid是mysql进程的PID,获取方法:
[root@vm-mysql ~]# ls -l /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd | grep -e ibdata -e ib_
lrwx------ 1 root root 64 Oct 16 14:16 10 -> /opt/vm-mysql/data2/ib_logfile1 (deleted)
lrwx------ 1 root root 64 Oct 16 14:16 4 -> /opt/vm-mysql/data2/ibdata1 (deleted)
lrwx------ 1 root root 64 Oct 16 14:16 9 -> /opt/vm-mysql/data2/ib_logfile0 (deleted)
但是,我们不能简单copy回源目录中,因在buffer pool有已经修改的页,这些页没有被写入磁盘,如果改变的页
没有永久写入,数据将会丢失,这些导致数据损坏和丢失。
同样原因,我们不能做MySQL备份,仅能coping那些文件。
因此,我们必须确保所有的修改全写入磁盘中。
我们现在能做的阻止写,且等待InnoDB刷新所有的页。
1.为了阻止写,我们要么停止应用程序或锁表。
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.01 sec)
2. show engine innodb status 中脏页刷新到磁盘,
---
LOG
---
Log sequence number 0 50355
Log flushed up to 0 50355
Last checkpoint at 0 50355
0 pending log writes, 0 pending chkp writes
39 log i/o's done, 0.00 log i/o's/second
加速脏页刷新,设置dirty pages percentage to zero:
mysql> set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected (0.00 sec)
3.确保所有后台进程已经完成自己的工作,也是重要的。
注意,插入缓冲线程,它的大小等于1
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2,
0 inserts, 0 merged recs, 0 merges
Hash table size 34679, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
4.后台写进程purge thread,清除所有事务。
------------
TRANSACTIONS
------------
Trx id counter 0 784
Purge done for trx's n:o < 0 0 undo n:o < 0 0
但是,如果上次事务没有需要清理操作Trx id计数比较大(如,SELECT),
在这种情况下,至少要保证InnoDB不再做任何写动作。
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
0 OS file reads, 81 OS file writes, 59 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
经历了4步,所有被修改脏页刷新到磁盘,现在开始copy InnoDB 文件到源目录:
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/4 /opt/vm-mysql/data2/ibdata1
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/9 /opt/vm-mysql/data2/ib_logfile0
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/10 /opt/vm-mysql/data2/ib_logfile1
5.修改ib*所属用户
chown -R mysql ib*
6.重启MySQLd
........
结论:
1.监控InnoDB文件 ibdata 和 ib_logfile* 是否存在
2.清楚恢复策略,否则不要重启MySQLd
参考:http://www.percona.com/blog/2012/08/10/recovery-deleted-ibdata1/
恢复的步骤和数据库版本没有太大关系。
在linux操作系统中,如果文件从操作系统级别别rm掉,之前打开的文件进程仍持有相应的文件句柄,
所指向的文件仍然可以读写,且该文件的描述符可以从/proc目录中获得(不关闭MySQLd情况下).
在删除3个文件后,MySQLd 仍是可以运行,对外服务的,MySQL一只保持InnoDB文件打开,因此,
在工作中有必要监控文件是否存在。
发现文件被删除之后,不能重启InnoDB,因为启动InnoDB,检测到ibdata1,ib_logfile0,ib_logfile1
不存在,所以,将创建对应的空文件,InnoDB数据字典是空的,InnoDB无法使用原先存在的ibd文件,故,
MySQL不重启,快速恢复删除的文件是可能的。
在MySQLd运行过程中,ibdata1,ib_logfile0,ib_logfile1一直运行在
/proc/vm-mysql.pid/fd目录下,其中vm-mysql.pid是mysql进程的PID,获取方法:
[root@vm-mysql ~]# ls -l /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd | grep -e ibdata -e ib_
lrwx------ 1 root root 64 Oct 16 14:16 10 -> /opt/vm-mysql/data2/ib_logfile1 (deleted)
lrwx------ 1 root root 64 Oct 16 14:16 4 -> /opt/vm-mysql/data2/ibdata1 (deleted)
lrwx------ 1 root root 64 Oct 16 14:16 9 -> /opt/vm-mysql/data2/ib_logfile0 (deleted)
但是,我们不能简单copy回源目录中,因在buffer pool有已经修改的页,这些页没有被写入磁盘,如果改变的页
没有永久写入,数据将会丢失,这些导致数据损坏和丢失。
同样原因,我们不能做MySQL备份,仅能coping那些文件。
因此,我们必须确保所有的修改全写入磁盘中。
我们现在能做的阻止写,且等待InnoDB刷新所有的页。
1.为了阻止写,我们要么停止应用程序或锁表。
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.01 sec)
2. show engine innodb status 中脏页刷新到磁盘,
---
LOG
---
Log sequence number 0 50355
Log flushed up to 0 50355
Last checkpoint at 0 50355
0 pending log writes, 0 pending chkp writes
39 log i/o's done, 0.00 log i/o's/second
加速脏页刷新,设置dirty pages percentage to zero:
mysql> set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected (0.00 sec)
3.确保所有后台进程已经完成自己的工作,也是重要的。
注意,插入缓冲线程,它的大小等于1
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2,
0 inserts, 0 merged recs, 0 merges
Hash table size 34679, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
4.后台写进程purge thread,清除所有事务。
------------
TRANSACTIONS
------------
Trx id counter 0 784
Purge done for trx's n:o < 0 0 undo n:o < 0 0
但是,如果上次事务没有需要清理操作Trx id计数比较大(如,SELECT),
在这种情况下,至少要保证InnoDB不再做任何写动作。
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
0 OS file reads, 81 OS file writes, 59 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
经历了4步,所有被修改脏页刷新到磁盘,现在开始copy InnoDB 文件到源目录:
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/4 /opt/vm-mysql/data2/ibdata1
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/9 /opt/vm-mysql/data2/ib_logfile0
[root@vm-mysql ~]# cp /proc/$(cat /opt/vm-mysql/data2/vm-mysql.pid)/fd/10 /opt/vm-mysql/data2/ib_logfile1
5.修改ib*所属用户
chown -R mysql ib*
6.重启MySQLd
........
结论:
1.监控InnoDB文件 ibdata 和 ib_logfile* 是否存在
2.清楚恢复策略,否则不要重启MySQLd
参考:http://www.percona.com/blog/2012/08/10/recovery-deleted-ibdata1/