视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
mysql误删除ibdata1之后的恢复方法_MySQL
2020-11-09 18:52:29 责编:小采
文档


bitsCN.com

mysql 误删除ibdata1之后如何恢复

如果误删除了在线服务器中mysql innodb相关的数据文件ibdata1以及日志文件 ib_logfile*,
应该怎样恢复呢?

这时候应该一身冷汗了吧?
==================================
先抽根烟,冷静一下。
==================================
再观察一下网站,发现一切都很正常,数据的读取与写入操作都完全正常。
这是怎么个情况?

其实,mysqld在运行状态中,会保持这些文件为打开状态,
即使把它们删除了,它们仍旧存在于文件系统中,mysqld仍然可以对其进行读写。


root@localhost:/var/lib/mysql# ls -la /proc/14101/fd/ | grep -e ibdata -e ib_
lrwx------ 1 root root Aug 7 23:29 3 -> /var/lib/mysql/ibdata1 (deleted)
lrwx------ 1 root root Aug 7 23:29 8 -> /var/lib/mysql/ib_logfile0 (deleted)
lrwx------ 1 root root Aug 7 23:29 9 -> /var/lib/mysql/ib_logfile1 (deleted)

14101是mysqld的pid(进程ID)

只要mysqld不结束,就可以通过proc文件系统找到这几个被删除的文件(已经被Mark为deleted状态)。

这时候应该松了一口气吧。只要把这几个文件复制回 /var/lib/mysql就行了吗?

事情绝对没有这么简单。

因为,在innodb的buffer pool中,有许多dirty page(就是内存中的数据已经被修改,但是没有写回文件中),
如果直接把文件复制回去,轻则数据丢失,重则ibdata1文件损坏。

备份mysql数据的时候,也不能直接备份这几个文件,是同样的道理。

我们必须保证所有buffer pool中的数据修改都保存到了硬盘文件上面,
为此,首先要停止更多的写入/更新/删除操作,然后等待innodb flush pages to disk.
停止写入的话,可以把网站应用关闭,或者lock tables:


mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 ROWS affected (0.37 sec)

这时就要等它flush结束,怎样知道有没有结束呢?观察checkpoint age就可以了。


mysql> SHOW engine innodb STATUS
---
LOG
---
Log SEQUENCE NUMBER 363096003
Log flushed up TO 363096003
LAST checkpoint at 363096003

checkpoint age 就是 Log sequence number的值减去 Last checkpoint at的值,
如果为0,那么表示所有的page都flush到硬盘文件中了。

这时就要等它flush结束,怎样知道有没有结束呢?观察checkpoint age就可以了。


mysql> SHOW engine innodb STATUS
---
LOG
---
Log SEQUENCE NUMBER 363096003
Log flushed up TO 363096003
LAST checkpoint at 363096003

checkpoint age 就是 Log sequence number的值减去 Last checkpoint at的值,
如果为0,那么表示所有的page都flush到硬盘文件中了。

为了加速这个flush的过程,可以这样设置一下:


mysql> SET global innodb_max_dirty_pages_pct=0;
Query OK, 0 ROWS affected (0.01 sec)

此外,还必须保证一些后台的线程完成了它们的工作,
比如insert buffer thread. ibuf的大小应该=1


-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: SIZE 1, free list len 398, seg SIZE 400,

还有purge thread,它应该purge了全部的transactions:


------------
TRANSACTIONS
------------
Trx id counter 0 1
Purge done FOR trx's n:o < 0 1 undo n:o < 0 0

还要确保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
332 OS file reads, 47 OS file writes, 32 OS fsyncs
0.00 reads/s, 0 avg bytes/READ, 0.00 writes/s, 0.00 fsyncs/s

然后把文件复制回去:


root@localhost:/var/lib/mysql# cp /proc/14101/fd/3 /var/lib/mysql/ibdata1
root@localhost:/var/lib/mysql# cp /proc/14101/fd/8 /var/lib/mysql/ib_logfile0
root@localhost:/var/lib/mysql# cp /proc/14101/fd/9 /var/lib/mysql/ib_logfile1
修改权限
root@localhost:/var/lib/mysql# chown -R mysql ib* 重启mysqld
root@localhost:/var/lib/mysql# /etc/init.d/mysql restart
结束~~~

结论:
1) 出现意外时,千万不能慌张,抽根烟先冷静一下。
2) 在解决方案不明确的时候,不要进行操作,比如重启mysqld,重启服务器。
3) 有必要监控mysql的ibdata等文件是否存在。

bitsCN.com

下载本文
显示全文
专题