hello,大家好,我是张张,「架构精进之路」公号作者。
在我们实际工作中,尤其在公司的测试环境下,经常会有多个业务方服务共用同一套服务器,部署自身MySQL环境。很不巧的是,会出现有MySQL数据文件被删除/误删除的情况发生。假如真的发生了,想想就很令人崩溃对不对?
先别着急,今天来跟大家分享一个对于MySQL数据文件被误删除后尝试恢复的办法。一旦发生上述情况,同时实例数据未做备份,是否有机会进行数据恢复呢?
接下来,就让我们来尝试下数据恢复过程的演示:
1.构建模拟数据
模拟数据准备:
复制 CREATE TABLE `t1` (
`id` int ( 11 ) DEFAULT NULL
) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4
mysql> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set ( 0.00 sec)
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
2.删除数据文件
在操作系统层进行数据文件的删除。
复制
[ root@admin- db12 test] # ll
total 112
- rw- r----- 1 mysql mysql 67 Nov 22 10:01 db.opt
- rw- r----- 1 mysql mysql 8556 Nov 22 11:48 t1.frm
- rw- r----- 1 mysql mysql 98304 Nov 22 11:48 t1.ibd
[ root@admin- db12 test] # pwd
/ mysql/ dba/ mysql/ multi/ 3303 / data/ test
[ root@admin- db12 test] # ll
total 112
- rw- r----- 1 mysql mysql 67 Nov 22 10:01 db.opt-rw-r----- 1 mysql mysql 8556 Nov 22 11:48 t1.frm-rw-r----- 1 mysql mysql 98304 Nov 22 11:48 t1.ibd
[ root@admin- db12 test] # rm - rf *
[ root@admin- db12 test] # ll
total 0
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
3.查询验证数据
在数据库层,查看当前表中数据,发现当前表数据目前已空空如也。
复制 #当前实例
mysql> select * from t1;
Empty set (0.00 sec)
4.OS层获取内存中的数据
当前实例没有关闭的情况下,查看实例pid。
复制
[root@admin-db62 test]# ps aux | grep 3303
root 21952 0.0 0.0 113304 1648 ? S 11:47 0:00 /bin/sh /mysql/dba/mysql/multi/3303/private/bin/mysqld_safe --defaults-file=/mysql/dba/mysql/multi/3303/etc/my.cnf
mysql 23356 0.2 1.1 19529408 1568416 ? Sl 11:47 0:04 /mysql/dba/mysql/multi/3303/private/bin/mysqld --defaults-file=/mysql/dba/mysql/multi/3303/etc/my.cnf --basedir=/mysql/dba/mysql/multi/3303/private --datadir=/mysql/dba/mysql/multi/3303/data --plugin-dir=/mysql/dba/mysql/multi/3303/private/lib/plugin --user=mysql --log-error=/mysql/dba/mysql/multi/3303/log/mysql-error.log --open-files-limit=65535 --pid-file=/mysql/dba/mysql/multi/3303/pid/mysql.pid --socket=/mysql/dba/mysql/multi/3303/socket/mysql.sock --port=3303
[root@admin-db62 fd]# cd /proc/23356/fd
[root@admin-db62 fd]# ll
lrwx------ 1 root root 64 Nov 22 11:52 39 -> /mysql/dba/mysql/multi/3303/data/mysql/time_zone.ibdlrwx------ 1 root root 64 Nov 22 11:52 4 -> /mysql/dba/mysql/multi/3303/data/ib_logfile0lrwx------ 1 root root 64 Nov 22 11:52 40 -> /mysql/dba/mysql/multi/3303/data/mysql/time_zone_transition.ibdlrwx------ 1 root root 64 Nov 22 11:52 42 -> /mysql/dba/mysql/multi/3303/data/test/t1.ibd (deleted)
通过上述操作我们发现,被我们干掉的数据文件显示状态为”deleted“,被删除。
5.获取处理数据
为保护好当前服务器现场、在另一台服务器上开始恢复数据。
复制 #目标端
[ root@admin- db64 3306 ] # nc - l 13306 > / mysql/ dba/ mysql/ multi/ 3306 / data/ t1.ibd #db64这台服务器上,3306实例中来恢复上述被删除的数据。/ mysql/ dba/ mysql/ multi/ 3306 / data为临时存放数据目录
#源端
lrwx------ 1 root root 64 Nov 22 11:52 42 -> /mysql/dba/mysql/multi/3303/data/test/t1.ibd (deleted)
[ root@admin- db62 fd] # cat 42 | nc 10.26 .65 .74 13306
#如上操作,将在OS层,内存里的数据拷贝并传输至远程恢复服务器上。
【注意】不要在本机进行恢复、保留线上环境,避免二次伤害。
6.恢复数据处理
在源端服务器进行数据恢复操作。
复制 [root@admin-db64 3306]# nc -l 13306 > /mysql/dba/mysql/multi/3306/data/t1.ibd
[root@admin-db64 3306]# cd data/
[root@admin-db64 data]# ll
total 100
-rw-r----- 1 mysql mysql 67 Nov 22 12:36 db.opt-rw-r--r-- 1 root root 98304 Nov 22 12:37 t1.ibd
[root@admin-db64 data]# chown -R mysql.mysql t1.ibd #更改属主
登录源端进行恢复实例操作:
复制 mysql > use test;
Database changed
mysql> show tables;
Empty set (0.00 sec)
#1、根据表结构创建表(不要告诉我表结构也已经没有了...)
CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
#2、discard 表空间
mysql> alter table t1 discard tablespace;
Query OK, 0 rows affected, 1 warning (0.01 sec)
#3、将上面准备好的数据文件放入正确目录
[root@admin-db64 data]#mv t1.ibd test/
#4、import 表空间
mysql> alter table t1 import tablespace;
Query OK, 0 rows affected, 1 warning (0.01 sec)
#5、查看数据是否可以正常查看
mysql> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 通过上述步骤的操作,发现数据已经可以正常查看,后面只需要将其备份出来,恢复到待恢复实例即可。此处不再赘述。
写在最后 今天跟大家分享了一种误删数据文件利用内存数据恢复的方法,其实还有一些其他的恢复方法,需要根据不同场景去选取最优的处理方案。
最后,需要跟大家强调的是:预防远比处理的意义大得多。
另外,在 MySQL 的集群方案中,会时不时地用到备份来恢复实例,因此定期检查备份的有效性也很有必要。如果你是业务开发同学,你可以用 show grants 命令查看账户的权限,如果权限过大,可以建议 DBA 同学给你分配权限低一些的账号;你也可以评估业务的重要性,和 DBA 商量备份的周期、是否有必要创建延迟复制的备库等等。
记住,数据和服务的可靠性不止是运维团队的工作,最终是各个合作环节一起保障的结果。