Mysql Innodb数据库误删除了文件,怎么恢复?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql Innodb数据库误删除了文件,怎么恢复?相关的知识,希望对你有一定的参考价值。

mysql Innodb数据库误删除ibdata1、ib_logfile0、ib_logfile1和日志文件,备份也只有前5、6天的备份,有没有办法把数据库恢复正常啊

经常性备份,如果binlog在的话,试试看……
- 恢复策略
前面说到未提交的事务和回滚了的事务也会记录Redo Log,因此在进行恢复时,这些事务要进行特殊的的处理.有2中不同的恢复策略:
A. 进行恢复时,只重做已经提交了的事务。
B. 进行恢复时,重做所有事务包括未提交的事务和回滚了的事务。然后通过Undo Log回滚那些未提交的事务。
- InnoDB存储引擎的恢复机制
MySQL数据库InnoDB存储引擎使用了B策略, InnoDB存储引擎中的恢复机制有几个特点:
A. 在重做Redo Log时,并不关心事务性。 恢复时,没有BEGIN,也没有COMMIT,ROLLBACK的行为。也不关心每个日志是哪个事务的。尽管事务ID等事务相关的内容会记入Redo Log,这些内容只是被当作要操作的数据的一部分。

B. 使用B策略就必须要将Undo Log持久化,而且必须要在写Redo Log之前将对应的Undo Log写入磁盘。Undo和Redo Log的这种关联,使得持久化变得复杂起来。为了降低复杂度,InnoDB将Undo Log看作数据,因此记录Undo Log的操作也会记录到redo log中。这样undo log就可以像数据一样缓存起来,而不用再redo log之前写入磁盘了。

包含Undo Log操作的Redo Log,看起来是这样的:

记录1: <trx1, Undo log insert <undo_insert …>>

记录2: <trx1, insert …>

记录3: <trx2, Undo log insert <undo_update …>>

记录4: <trx2, update …>

记录5: <trx3, Undo log insert <undo_delete …>>

记录6: <trx3, delete …>

C. 到这里,还有一个问题没有弄清楚。既然Redo没有事务性,那岂不是会重新执行被回滚了的事务?确实是这样。同时Innodb也会将事务回滚时的操作也记录到redo log中。回滚操作本质上也是对数据进行修改,因此回滚时对数据的操作也会记录到Redo Log中。

一个回滚了的事务的Redo Log,看起来是这样的:

记录1: <trx1, Undo log insert <undo_insert …>>

记录2: <trx1, insert A…>

记录3: <trx1, Undo log insert <undo_update …>>

记录4: <trx1, update B…>

记录5: <trx1, Undo log insert <undo_delete …>>

记录6: <trx1, delete C…>

记录7: <trx1, insert C>

记录8: <trx1, update B to old value>

记录9: <trx1, delete A>

一个被回滚了的事务在恢复时的操作就是先redo再undo,因此不会破坏数据的一致性.
- InnoDB存储引擎中相关的函数
Redo: recv_recovery_from_checkpoint_start()
Undo: recv_recovery_rollback_active()
Undo Log的Redo Log: trx_undof_page_add_undo_rec_log()
参考技术A 还原也是有节点的,
既然只有前5、6天的备份,那还原的话也只能还原到前5、6天的情况了。

个人认为:重要的数据备份的频率最好调高一点,以免出现问题时造成不必须的损失。
参考技术B 数据非常重要的话建议还是找专业的地方恢复,自己尝试恢复的话很可能导致数据损坏无法恢复的 参考技术C bin-log也没了吗

误删除innodb ibdata数据文件-之恢复

今天在群里看到有人说不熟悉innodb把ibdata(数据文件)和ib_logfile(事务日志)文件误删除了。不知道怎么解决。当时我也不知道怎么办。后来查阅相关资料。终找到解决方法。其实恢复也挺简单的。我们不知道的时候就觉得难了。谁说不是这样呢?

下面我们就来模拟生产环境下,人为删除数据文件和重做日志文件。然后详细说明恢复步骤。

1.用sysbench模拟数据的写入,如下所示:

复制代码
[root@yayun-mysql-server ~]# sysbench --test=oltp --oltp-table-size=1000000 --oltp-read-only=off --init-rng=on --num-threads=16 --max-requests=0 --oltp-dist-type=uniform --max-time=1800 --mysql-user=root --mysql-socket=/tmp/mysqld.sock --mysql-password=123456 --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=complex prepare      
sysbench 0.4.10:  multi-threaded system evaluation benchmark

Creating table \'sbtest\'...
Creating 1000000 records in table \'sbtest\'...
复制代码

2.使用命令rm -f ib*删除数据文件和事务日志文件:

复制代码
[root@yayun-mysql-server mysql]# ls
employees    ib_logfile1       mysql-bin.000003  mysql-bin.000008  performance_schema  world_innodb                  yayun-mysql-server.pid
general.log  menagerie         mysql-bin.000004  mysql-bin.000009  sakila              world_myisam
host         mysql             mysql-bin.000005  mysql-bin.000010  sbtest              xtrabackup_binlog_pos_innodb
ibdata1      mysql-bin.000001  mysql-bin.000006  mysql-bin.index   slow-query.log      yayun
ib_logfile0  mysql-bin.000002  mysql-bin.000007  percona           test                yayun-mysql-server.err
[root@yayun-mysql-server mysql]# rm -f ib*
[root@yayun-mysql-server mysql]# 
复制代码

下面我们来看看如何恢复:

若此时发现数据库还能正常工作,数据依然可读可写,切记:这个时候千万不要把mysqld进程杀死,否则真没法挽救了,你就等着哭吧。

复制代码
(root@yayun 20:42:25pm> ) [yayun]>select * from t1;
+----+-------+
| id | name  |
+----+-------+
|  1 | yayun |
|  2 | atlas |
|  3 | mysql |
+----+-------+
3 rows in set (0.00 sec)

(root@yayun 20:42:28pm> ) [yayun]>insert into t1 select 4,\'python\';
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

(root@yayun 20:42:48pm> ) [yayun]>select * from t1;                
+----+--------+
| id | name   |
+----+--------+
|  1 | yayun  |
|  2 | atlas  |
|  3 | mysql  |
|  4 | python |
+----+--------+
4 rows in set (0.00 sec)

(root@yayun 20:42:50pm> ) [yayun]>
复制代码

我这里读写都正常。所以我们能够恢复成功的。
(1)首先,先找到mysqld进程的pid,如下所示:

[root@yayun-mysql-server ~]# netstat -nltp | grep mysqld
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      5725/mysqld         
[root@yayun-mysql-server ~]# 

可见mysqld的pid是5725,这一步是关键的一步。

(2)使用如下命令查看结果(非常重要)

[root@yayun-mysql-server ~]# ll /proc/5725/fd | egrep \'ib_|ibdata\'
lrwx------. 1 root root 64 Apr 30 20:44 10 -> /data/mysql/ib_logfile1 (deleted)
lrwx------. 1 root root 64 Apr 30 20:44 4 -> /data/mysql/ibdata1 (deleted)
lrwx------. 1 root root 64 Apr 30 20:44 9 -> /data/mysql/ib_logfile0 (deleted)
[root@yayun-mysql-server ~]# 

这里有相关很重要的知识,童鞋们自行查阅,删除一个文件时,并不是真正删除,而是打一个标记,同样在我们mysql数据库中,delete一条记录实际的删除操作也没有发生。
上面显示的结果中,其中10,4,9就是我们需要恢复的文件。

(3)在恢复文件前,需要执行flush tables with read lock,确保数据库没有写入操作,以便我们完成恢复

(root@yayun 20:55:26pm> ) [(none)]>flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

(root@yayun 20:55:31pm> ) [(none)]>

那么我们如何确定没有数据写入呢?分几个步骤查看

(1)设置脏页刷新比例(让脏页尽快刷新到磁盘)

(root@yayun 20:55:31pm> ) [(none)]>set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected (0.00 sec)

(root@yayun 20:57:42pm> ) [(none)]>

(2)查看binlog日志写入情况,确保File和Position的值没有发生变化

复制代码
(root@yayun 20:57:42pm> ) [(none)]>show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000010 | 61704130 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

(root@yayun 20:59:11pm> ) [(none)]>
复制代码

(3)查看innodb状态信息,确保脏页已经刷新到磁盘

复制代码
(root@yayun 20:59:11pm> ) [(none)]>show engine innodb status\\G
------------
TRANSACTIONS
------------
Trx id counter B9E0F
Purge done for trx\'s n:o < B9E0C undo n:o < 0    #确保后台线程purge把undo log全部清刷掉

-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 2543, seg size 2545, 0 merges  #确保合并插入缓存等于1

---
LOG
---
Log sequence number 6173930288
Log flushed up to   6173930288            #确保这里三个值保持一致,并且不再变化
Last checkpoint at  6173930288

Buffer pool size   65534
Free buffers       50513
Database pages     15020
Old database pages 5506
Modified db pages  0                       #确保脏页数量为0

--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
1 read views open inside InnoDB
Main thread process no. 5725, id 140014471358208, state: waiting for server activity
Number of rows inserted 1000004, updated 1995, deleted 0, read 2008
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s           #确保插入,更新,删除为0
复制代码

上面我们都确认后,就可以进行恢复操作了。记得前面我们查看要恢复的文件的命令吧,我们的mysqld进程的pid是5725,我们再次看看需要恢复的文件

[root@yayun-mysql-server ~]# ll /proc/5725/fd | egrep \'ib_|ibdata\'
lrwx------. 1 root root 64 Apr 30 20:44 10 -> /data/mysql/ib_logfile1 (deleted)
lrwx------. 1 root root 64 Apr 30 20:44 4 -> /data/mysql/ibdata1 (deleted)
lrwx------. 1 root root 64 Apr 30 20:44 9 -> /data/mysql/ib_logfile0 (deleted)
[root@yayun-mysql-server ~]# 

把10,4,9文件cp到原来mysql的数据目录下:

[root@yayun-mysql-server ~]# cd /proc/5725/fd
[root@yayun-mysql-server fd]# cp 10 /data/mysql/ib_logfile1
[root@yayun-mysql-server fd]# cp 4 /data/mysql/ibdata1
[root@yayun-mysql-server fd]# cp 9 /data/mysql/ib_logfile0
[root@yayun-mysql-server fd]# 

修改文件权限

复制代码
[root@yayun-mysql-server ~]# cd /data/mysql
[root@yayun-mysql-server mysql]# chown -R mysql.mysql ib*
[root@yayun-mysql-server mysql]# ll | egrep \'ib_|ibdata1\'
-rw-r--r-- 1 mysql mysql 866123776 Apr 30 21:13 ibdata1
-rw-r--r-- 1 mysql mysql  67108864 Apr 30 21:13 ib_logfile0
-rw-r--r-- 1 mysql mysql  67108864 Apr 30 21:11 ib_logfile1
[root@yayun-mysql-server mysql]# 
复制代码

重启mysql,修复完成

[root@yayun-mysql-server mysql]# /etc/init.d/mysqld restart
Shutting down MySQL...                                     [  OK  ]
Starting MySQL....                                         [  OK  ]
[root@yayun-mysql-server mysql]# 

注意:生产环境切勿测试,童鞋们可以自己开启虚拟机进行测试。

 

参考资料

《MySQL 管理之道,性能调优,高可用与监控》


原文blog:Atlas的博客 http://www.cnblogs.com/gomysql

以上是关于Mysql Innodb数据库误删除了文件,怎么恢复?的主要内容,如果未能解决你的问题,请参考以下文章

误删除innodb ibdata数据文件-之恢复

mysql数据库误删除后的数据恢复操作说明

mysql数据删除恢复

MySQL删除表怎么恢复?

sqlserver数据库数据被删除了怎么还原

MYSQL随笔四 MySQL误删除ibd文件导致数据库无法启动