一、前言
在平时工作中,小伙伴们有没有手抖误执行过没有带where条件的delete语句或者update语句?这种语句会导致大量的数据被删除或者更新,这个时候小伙伴们会不会很慌,不知道怎么办?今天就来教你如何恢复数据。
二、数据安全策略
为了保证数据库中数据的安全性,我们公司的DBA(数据库管理员)一般会对数据库做下面这两个操作:
- 定期对数据库进行备份:这个操作可能是一天一次,也可能是一周一次。
- 开启binlog日志:这个binlog日志非常有用,比如主库和从库之间数据的同步,就是通过这个日志来实现的,我们也可以拿这个日志来做数据恢复。
sql
SHOW VARIABLES LIKE 'log_bin';
我们可以通过上面的命令查看是否开启binlog日志,ON代表已经开启。
三、数据恢复案例演示
(声明:该案例是在windows系统上完成的)
准备测试数据
sql
create table sys_post
(
id bigint auto_increment comment '岗位ID'
primary key,
post_code varchar(64) not null comment '岗位编码',
name varchar(50) default '' not null comment '岗位名称',
description varchar(255) default '' not null comment '描述',
status tinyint(1) default 1 not null comment '状态(1正常 0停用)',
create_time timestamp default *CURRENT_TIMESTAMP* not null on update *CURRENT_TIMESTAMP*,
update_time timestamp null on update *CURRENT_TIMESTAMP*,
is_deleted tinyint default 0 not null comment '删除标记(0:可用 1:已删除)'
)
comment '岗位信息表' charset = utf8mb3;
INSERT INTO sys_post (id, post_code, name, description, status, create_time, update_time, is_deleted) VALUES (5, 'dsz', '董事长', '1', 1, '2022-05-24 10:33:53', null, 0);
INSERT INTO sys_post (id, post_code, name, description, status, create_time, update_time, is_deleted) VALUES (6, 'zjl', '总经理', '2', 1, '2022-05-24 10:34:08', null, 0);
INSERT INTO sys_post (id, post_code, name, description, status, create_time, update_time, is_deleted) VALUES (7, 'wz', '网咨', '', 1, '2022-05-27 08:56:41', '2022-05-27 08:56:41', 1);
INSERT INTO sys_post (id, post_code, name, description, status, create_time, update_time, is_deleted) VALUES (8, 'yyzj', '运营总监', '', 1, '2022-06-08 17:14:21', null, 0);
备份数据
因为我们的DBA会定期备份数据,所以我们这一步是模拟数据备份这个动作的,通过mysqldump命令进行数据备份。
sql
mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot -p guigu-auth > backup.sql

(注意:该命令是在操作系统的terminal终端执行的(非MySQL客户端),其中guigu-auth为测试库的名字)
验证备份文件:执行成功后,检查生成的backup.sql文件是否包含完整的数据库结构和数据,部分截图如下:

下面对上述命令的参数做一下说明:
--single-transaction:表示在备份过程中,使用单个事务来确保数据的一致性。
--flush-logs:表示在备份过程中,刷新日志文件,以便在备份完成后,日志文件中的内容不会影响到备份数据。
--source-data=2:表示在备份过程中,将主服务器的二进制日志位置信息也备份到文件中。这个参数比较重要,用于在恢复数据时找到位置信息。老版本叫做master-data
--routines:表示在备份过程中,备份存储过程和函数。
--opt:表示使用优化过的备份方式,以提高备份速度和减少备份文件的大小。
将测试表的数据删除
我们将表数据删除一下,方便后边做数据恢复的验证
sql
delete from sys_post;
将sys_post表数据给清空了。
数据恢复
数据恢复的原理就是以定期备份文件为全量基础,加上binlog的增量数据,从而恢复数据到任何一秒。
我们首先需要从上面步骤中生成的备份文件中找到最后的binlog写入位置。

从上图可以得知,备份文件一直包含了**-bin.000184的157这个位置,也就是说增量恢复只需要从157这个位置开始即可。接着我们执行以下命令:
sql
mysqlbinlog --no-defaults -vv "C:\ProgramData\MySQL\MySQL Server 8.1\Data\CC-bin.000184"
(注意:也是在windows的terminal终端执行)

从上图结果可以看到,这条删除命令对应的binlog执行的位置是从560到591。从157到560的这中间的数据就是增量的数据,将这些数据整理成增量sql:

sql
mysqlbinlog --no-defaults --start-position=157 --stop-position=560 "C:\ProgramData\MySQL\MySQL Server 8.1\Data\CC-bin.000184" > backup_inc.sql
执行完成后,服务器上已经有backup.sql和backup_inc.sql这两个文件。
参数解释:
- --start-position=157:指定从二进制日志文件的157字节偏移量开始解析。
- --stop-position=560:设定解析终止于560字节偏移量,与起始位置共同划定精确的操作范围。

接着我们通过执行脚本的方式,去执行一下backup.sql和backup_inc.sql这两个文件,执行完成后,再去查询数据:

发现数据已经恢复回来了。
总结
数据恢复是一个很值得我们认真去学习的技能,但是大家在日常工作中,对于需要执行的sql更应该认真去检查,以免出错,防患于未然。