MySql基于二进制日志增量恢复数据库到任意指定位置
1、基本原理
MySql的二进制日志将对数据库的每一个操作都完整的记录在日志中,那么就可以根据需求在失误操作的时候找到合适的位置或时间,然后通过从日志中提取截止到这一位置的所有操作过程,然后将这一导出的SQL再次让数据库执行一次,那么数据便可以恢复到期望的结果,这一方式可以实现恢复到任意的位置或者时间。
这一模式就像在一块雪地里走路一样,每一步都记录下来,如果有一步或者几步走的不是自己期望的,那么就可以在记录的日志中找到出错的那一步,然后将雪里重新涂平,没有任何的脚印,这个时候便可以按日志里找到的符合自己意愿的所有走过的记录重新在雪地里走一次,这样下来,便可以实现恢复到出错之前的位置所有的走步,比如下图中这样一块长方形的雪地:
当走到第10步的时候,发现自己已经走错了,这个便是期望之外的位置,这个时候可以将这块雪里重新铺满雪,按照之前的日志记录,重新走一次第1至第9步,然后便可以继续走下去。
2、实验测试
下面我们在CentOS上安装mysql,做一个真实的测试,在这个测试中,我会创建一个全新的数据库test,开启二进制日志功能,在test数据库中添加一个测试的表t1,然后这个时候我们做一个全备份,并刷新一下日志;之后我会在t1表里添加几条测试记录,并做一个模拟删除所有记录的误操作;最后我将使用日志的功能,恢复误操作之前的所有数据。
2.1环境与初始化
操作系统:CENTOS 7.2,数据库系统:maridb-server 5.5.64
数据库安装
yum install mariadb-server mariadb #安装系统
systemctl start mariadb.service #启动数据库服务
mysql_secure_installation #启动数据库初始化向导
#以下配置可选,为了可以在其它计算机上访问数据库,可以给root分配任意主机的访问权限
mysql -uroot #进入数据库
MariaDB [(none)]> grant all on *.* to root@'%' ; #给root用户分配访问权限MariaDB [(none)]> flush privileges; #刷新权限
数据库配置,修改/etc/my.cnf,开启二进制日志功能
vi /etc/my.cnf ##添加如下行
log-bin=cl_bin ##开启二进制日志功能
#如下为可选的配置,可配可不配,这里我不配置
#设置日志格式
#binlog_format = mixed
#设置binlog清理时间
#expire_logs_days = 7
#binlog每个日志文件大小max_binlog_size = 100m
#binlog缓存大小
#binlog_cache_size = 4m
#最大binlog缓存大小
#max_binlog_cache_size = 512m
完成以上配置后,重新启动数据库
systemctl restart mariadb.service #启动数据库服务
创建数据库test,并添加表t1
mysql -uroot #进入数据库
MariaDB [(none)]> show variables like 'log_bin';
#查询数据库的二进制功能是否已经开启#如果顺利,应该显示如下的内容:#log_bin | ON
#下面创建数据库
MariaDB [(none)]> create database test default charset=utf8;
#下面创建表t1
MariaDB [(none)]> use test;
MariaDB [test]> create table t1(id int not null auto_increment,k varchar(20) default null,v varchar(50) default null , primary key (id)) default charset=utf8;
完成以上步骤,可以查看一下数据结构如下:
这个时候,我们可以对数据库做一个全备份,作为以后恢复的一个基准备份
mysqldump -uroot test > test_bak_20191227.sql #备份数据库
mysqldump -uroot --all-databases > mysql_bak_20191227.sql #备份全部,以防万一,这里可选操作,与实验相关不大
mysqladmin -uroot flush-logs #刷新数据库日志
#或者以下面的方式刷新数据库日志
mysql -urootMariaDB [test]>flush logs; #刷新日志
MariaDB [test]> show binary logs;#显示日志列表
当显示日志列表时,应该可以看到一个新的日志文件产生,如下cl_bin.000008:
我们查看一下cl_bin.000008与cl_bin.000007的日志内容
MariaDB [test]> show binlog events in ‘cl_bin.000008’;
MariaDB [test]> show binlog events in ‘cl_bin.000007’;
可以注意到,在cl_bin.000007的日志中包含了我们创建数据库的细节,cl_bin.000008是一个刷新之后的新日志。
最后,我对数据库的test的表t1插入一些数据
MariaDB [none]> use test; #空表
MariaDB [test]> select * from t1; #空表
MariaDB [test]> insert into t1(k,v) values('test-k-01','test-value-001'); #插入演示数据
MariaDB [test]> insert into t1(k,v) values('test-k-02','test-value-002'); #插入演示数据
MariaDB [test]> insert into t1(k,v) values('test-k-03','test-value-003'); #插入演示数据
2.2误操作
下面我们可以进行模拟误操作
mysql -uroot #进入数据库
MariaDB [test]> delete from t1; #这是一个误操作,清空了t1表的所有数据
2.2恢复到误操作之前的数据
下面的操作,就是要实现恢复误删除表所有记录之前的所有数据。
第一步,我们先恢复到上面做好的全备份,这里可以使用数据库的全备份,也可以使用test数据库的全备份。
mysql -uroot < mysql_bak_20191227.bak #使用数据库全备份#使用test的全备份
mysql -urootMariaDB [(none)]> use test;
MariaDB [test]> source test_bak_20191227.sql
完成恢复全备份后,可以断定,这时候的数据就是我们在插入演示数据之前的一样,只是完成数据结构的初始化,t1表当然是空的。
第二步,恢复日志
首先,我可以看一下最新的日志里有什么内容,找到出错的那一步的位置。
MariaDB [test]> show binlog events in 'cl_bin.000008';
这里标记为红色的第1039步的操作,就是我刚刚做的误操作,那么,就从这个日志中提取截止到1039位置的日志,并再次导入到数据库即可。
下面,我开始提取日志,既然需要提取日志,就要知道日志在哪里,此前已经说过了配置log_bin项,我们配置的是cl_bin,也就是说在mysql数据目录下面以cl_bin为名的文件,mysql数据目录又在哪里呢,可以到数据库里查看一下
我们看到了数据目录在/var/lib/mysql,那么就可以进入这个目录
cd /var/lib/mysql/
mysqlbinlog --stop-position=1039 cl_bin.000008 > recovery.sql; #这一步最关键,
提取到1039步的日志到recovery.sql文件
最后,使用这个recovery.sql文件来恢复数据
mysql -uroot < recovery.sql;mysql -uroot #再次登录数据库
MariaDB [(none)]> use test; #使用test
MariaDB [test]> select * from t1; #查看结果
大功告成!!!