文章插图
日常工作中 , 总会有因手抖、写错条件、写错表名、错连生产库造成的误删库表和数据的事情发生 。那么 , 如果连数据都恢复不了 , 还要什么 DBA 。
1 前言数据恢复的前提的做好备份 , 且开启 binlog , 格式为 row 。如果没有备份文件 , 那么删掉库表后就真的删掉了 , lsof 中还有记录的话 , 有可能恢复一部分文件 。但若刚好数据库没有打开这个表文件 , 那就只能跑路了 。如果没有开启 binlog , 那么恢复数据后 , 从备份时间点开始的数据都没了 。如果 binlog 格式不为 row , 那么在误操作数据后就没有办法做闪回操作 , 只能老老实实地走备份恢复流程 。
2 直接恢复直接恢复是使用备份文件做全量恢复 , 这是最常见的场景 。
2.1 MySQLdump 备份全量恢复【删库一定要跑路吗?手把手教你MySQL数据恢复】使用 mysqldump 文件恢复数据非常简单 , 直接解压了执行:
gzip -d backup.sql.gz | mysql -u<user> -h<host> -P<port> -p
2.2 xtrabackup 备份全量恢复恢复过程:
# 步骤一:解压(如果没有压缩可以忽略这一步)innobackupex --decompress <备份文件所在目录># 步骤二:应用日志innobackupex --Apply-log <备份文件所在目录># 步骤三:复制备份文件到数据目录innobackupex --datadir=<MySQL数据目录> --copy-back <备份文件所在目录>
2.3 基于时间点恢复基于时间点的恢复依赖的是 binlog 日志 , 需要从 binlog 中找过从备份点到恢复点的所有日志 , 然后应用 。我们测试一下 。新建测试表:
chengqm-3306>>show create table mytest.mytest G;*************************** 1. row ***************************Table: mytestCreate Table: CREATE TABLE `mytest` (`id` int(11) NOT NULL AUTO_INCREMENT,`ctime` datetime DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8
每秒插入一条数据:[mysql@mysql-test ~]$ while true; do mysql -S /tmp/mysql.sock -e 'insert into mytest.mytest(ctime)values(now())';date;sleep 1;done
备份:
[mysql@mysql-test ~]$ mysqldump --opt --single-transaction --master-data=https://www.isolves.com/it/sjk/MYSQL/2020-08-27/2 --default-character-set=utf8 -S /tmp/mysql.sock -A > backup.sql
找出备份时的日志位置:
[mysql@mysql-test ~]$ head -n 25 backup.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE' -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000032', MASTER_LOG_POS=39654;
假设要恢复到 2019-08-09 11:01:54 这个时间点 , 我们从 binlog 中查找从 39654 到 019-08-09 11:01:54 的日志 。
[mysql@mysql-test-83 ~]$ tail -n 20 backup_inc.sql......### INSERT INTO `mytest`.`mytest`### SET###@1=161 /* INT meta=0 nullable=0 is_null=0 */###@2='2019-08-09 11:01:53' /* DATETIME(0) meta=0 nullable=1 is_null=0 */......
当前数据条目数:-- 2019-08-09 11:01:54之前的数据条数chengqm-3306>>select count(*) from mytest.mytest where ctime < '2019-08-09 11:01:54';+----------+| count(*) |+----------+|161 |+----------+1 row in set (0.00 sec)-- 所有数据条数chengqm-3306>>select count(*) from mytest.mytest;+----------+| count(*) |+----------+|180 |+----------+1 row in set (0.00 sec)
然后执行恢复:# 全量恢复[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup.sql# 应用增量日志[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup_inc.sql
检查数据:chengqm-3306>>select count(*) from mytest.mytest;+----------+| count(*) |+----------+|161 |+----------+1 row in set (0.00 sec)chengqm-3306>>select * from mytest.mytest order by id desc limit 5;+-----+---------------------+| id| ctime|+-----+---------------------+| 161 | 2019-08-09 11:01:53 || 160 | 2019-08-09 11:01:52 || 159 | 2019-08-09 11:01:51 || 158 | 2019-08-09 11:01:50 || 157 | 2019-08-09 11:01:49 |+-----+---------------------+5 rows in set (0.00 sec)
已经恢复到 2019-08-09 11:01:54 这个时间点 。3 恢复一个表3.1 从 mysqldump 备份恢复一个表假设要恢复的表是 mytest.mytest:
# 提取某个库的所有数据sed -n '/^-- Current Database: `mytest`/,/^-- Current Database:/p' backup.sql > backup_mytest.sql# 从库备份文件中提取建表语句sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `mytest`/!d;q' backup_mytest.sql > mytest_table_create.sql# 从库备份文件中提取插入数据语句grep -i 'INSERT INTO `mytest`' backup_mytest.sql > mytest_table_insert.sql# 恢复表结构到 mytest 库mysql -u<user> -p mytest < mytest_table_create.sql# 恢复表数据到 mytest.mytest 表mysql -u<user> -p mytest <mytest_table_insert.sql
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 取出上一条下一条的 sql语句
- 一个用Java实现的超轻量级RESTful Web服务示例
- 教你一个万能的PPT排版小技巧,简单易学,而且什么场合都能用
- 冥王阿茶是谁 冥王阿茶百度百科
- 割双眼皮多久才能喝酒呢?
- 杨玉环的身高及体重 杨玉环体型
- 西班牙参与一战和二战吗 西班牙没有参加二战
- 小人国是指哪一个星系?
- 教师资格证审核要多久?
- 黄忠是一位什么样的人 黄忠一把年纪都活在了