一、模拟环境创建
mysql> create database testdb;
mysql> use testdb;
mysql> CREATE TABLE `people` (
`name` varchar(20) DEFAULT NULL,
`age` varchar(20) DEFAULT NULL,
`birth` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
mysql> CREATE TABLE `pet` (
`name` varchar(20) DEFAULT NULL,
`owner` varchar(20) DEFAULT NULL,
`species` varchar(20) DEFAULT NULL,
`sex` char(1) DEFAULT NULL,
`birth` date DEFAULT NULL,
`death` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
mysql> INSERT INTO pet VALUES ('Fluffy','Harold','cat','f','1993-02-04',NULL);
二、数据库完整备份
[root@bogon /]# mysqldump -uroot -proot --single-transaction --flush-logs --master-data=2 --databases testdb --events --routines --triggers > /testdb.sql
关于参数的详细说明可以查看这篇文章
三、模拟删表及前后的数据操作
mysql> use testdb;
mysql> INSERT INTO pet VALUES ('Claws','Gwen','cat','m','1994-03-17',NULL);
mysql> drop table pet;
mysql> INSERT INTO `testdb`.`people`(`name`, `age`, `birth`) VALUES ('yuantu', '12', '2022-02-26');
mysql> exit
四、开始数据恢复
- 先刷新binlog日志,创建一个新的日志文件
mysql> flush logs; -- 执行会创建一个新的日志文件
Query OK, 0 rows affected (0.03 sec)
mysql> show binary logs; --flush logs刷新的日志文件为 mysql-bin.000003
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 | 1831 | No |
| mysql-bin.000002 | 711 | No |
| mysql-bin.000003 | 157 | No |
+------------------+-----------+-----------+
3 rows in set (0.00 sec)
mysql> exit
- 查看完整备份文件内容,获取备份时新创建的日志信息
[root@bogon /]# more /testdb.sql
完整备份刷新的binlog日志文件为: mysql-bin.000002
日志位置为: 157
flush logs刷新的日志文件为: mysql-bin.000003
由此可知 删表以及其他的数据操作都在 mysql-bin.000002
- 根据删表的大致时间范围 确定binlog日志事件位置
[root@bogon /]# mysqlbinlog --start-datetime="2022-02-26 20:50:00" --stop-datetime="2022-02-26 23:55:00" --verbose /usr/local/mysql/data/mysql-bin.000002 | grep -C 15 "DROP TABLE"
可以看到 DROP TABLE 记录的日志位置 在 543 - 675 之间
- 先将完整备份恢复
mysql> source /testdb.sql
mysql> use testdb;
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| people |
| pet |
+------------------+
2 rows in set (0.00 sec)
mysql> select * from pet;
+--------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
+--------+--------+---------+------+------------+-------+
1 row in set (0.00 sec)
mysql> select * from people;
Empty set (0.00 sec)
exit
模拟故障删除的步骤
先在要删除的表 pet 插入1条数据
然后删除表 pet (知道删表操作所在的时间范围)
然后在people表插入1条数据
归纳一下开始故障恢复后得到的信息
完整备份刷新的binlog日志文件为: mysql-bin.000002
日志位置为: 157
flush logs刷新的日志文件为: mysql-bin.000003
删表操作的日志位置 在 543 - 675 之间
那接下来的恢复步骤就是
根据 mysql-bin.000002 先恢复log日志里 删表之前 记录的数据库操作
然后跳过删表的操作记录,恢复删表后 log日志里记录的数据库操作
- 删表前的数据库操作恢复
[root@bogon /]# mysqlbinlog --start-position=157 --stop-position=543 /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -proot
- 删表后的数据库操作恢复
[root@bogon /]# mysqlbinlog --start-position=675 /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -proot
- 查看数据恢复状况
mysql> use testdb;
mysql> select * from pet;
+--------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+--------+--------+---------+------+------------+-------+
2 rows in set (0.00 sec)
mysql> select * from people;
+--------+------+------------+
| name | age | birth |
+--------+------+------------+
| yuantu | 12 | 2022-02-26 |
+--------+------+------------+
1 row in set (0.00 sec)
至此,完整备份后的binlog日志除了删表操作,其他数据已完全恢复。
tips
假设
1.完整备份时刷新的binlog日志文件为:mysql-bin.000011
2.完整备份恢复之前手动flush log刷新的binlog日志文件为:mysql-bin.000015
3.发现记录删除表的日志文件为:mysql-bin.000014
那么完整备份恢复后 我们需要先将 mysql-bin.000011 mysql-bin.000012 mysql-bin.000013 整个binlog日志恢复
[root@bogon /]# mysqlbinlog mysql-bin.000011 mysql-bin.000012 mysql-bin.000013 | mysql -uroot -proot
然后针对 mysql-bin.000014 按照文章内 mysql-bin.000002 的描述进行处理
删库的解决步骤
1.恢复完整备份
2.查看删库操作在哪个日志文件内,记录删库操作前面的日志位置(假设为 790)
3.恢复完整备份后生成的所有日志文件(记录删库操作的日志文件除外)
4.记录删库操作的日志文件恢复到 790
参考 MySQL官网文档 - 备份以及恢复 章节