一、binlog2sql 概述
从MySQL binlog解析出需要的SQL。根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。
1.1 用途
- 数据快速回滚(闪回)
- 主从切换后新master丢数据的修复
- 从binlog生成标准SQL,带来的衍生功能
GitHub项目地址:https://github.com/danfengcao/binlog2sql
1.2 所需环境
- Python 2.7, 3.4+
- MySQL 5.6, 5.7
- binlog 模式为 row
1.3 闪回原理
MySQL binlog以event的形式,记录了MySQL server从启用binlog以来所有的变更信息,能够帮助重现这之间的所有变化。MySQL引入binlog主要有两个目的:一是为了主从复制;二是某些备份还原操作后需要重新应用binlog。
有三种可选的binlog格式,各有优缺点:
- statement:基于SQL语句的模式,binlog数据量小,但是某些语句和函数在复制过程可能导致数据不一致甚至出错;
- row:基于行的模式,记录的是行的完整变化。很安全,但是binlog会比其他两种模式大很多;
- mixed:混合模式,根据语句来选用是statement还是row模式;
既然binlog以event形式记录了所有的变更信息,那么我们把需要回滚的event,从后往前回滚回去即可。
1 | 对于 delete 操作,从 binlog 提取出 delete 信息,反向生成 insert 回滚语句; |
二、binlog2sql 安装
2.1 安装依赖包
1 | yum install -y git wget |
2.1 安装python3 pip3
1 | yum install -y python3 |
2.2 安装 binlog2sql
1 | git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql |
三、binlog2sql 使用
3.1 使用前配置
MySQL server必须设置以下参数
1 | [mysqld] |
在运行中的mysql中查看参数
1 | mysql> show variables like 'server_id'; |
用来闪回数据的user需要的最小权限集合
1 | select, super/replication client, replication slave |
权限说明
- select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
- super/replication client:两个权限都可以,需要执行’SHOW MASTER STATUS’, 获取server端的binlog列表
- replication slave:通过BINLOG_DUMP协议获取binlog内容的权限
3.2 基本用法
解析出标准SQL
1 | python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t test3 test4 --start-file='mysql-bin.000002' |
解析出回滚SQL
1 | python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttest3 --start-file='mysql-bin.000002' --start-position=763 --stop-position=1147 |
3.3 参数说明
mysql连接配置
-h host; -P port; -u user; -p password
解析模式
–stop-never 持续解析binlog。可选。默认False,同步至执行命令时最新的binlog位置。
-K, –no-primary-key 对INSERT语句去除主键。可选。默认False
-B, –flashback 生成回滚SQL,可解析大文件,不受内存限制。可选。默认False。与stop-never或no-primary-key不能同时添加。
–back-interval -B模式下,每打印一千行回滚SQL,加一句SLEEP多少秒,如不想加SLEEP,请设为0。可选。默认1.0。
解析范围控制
–start-file 起始解析文件,只需文件名,无需全路径 。必须。
–start-position/–start-pos 起始解析位置。可选。默认为start-file的起始位置。
–stop-file/–end-file 终止解析文件。可选。默认为start-file同一个文件。若解析模式为stop-never,此选项失效。
–stop-position/–end-pos 终止解析位置。可选。默认为stop-file的最末位置;若解析模式为stop-never,此选项失效。
–start-datetime 起始解析时间,格式’%Y-%m-%d %H:%M:%S’。可选。默认不过滤。
–stop-datetime 终止解析时间,格式’%Y-%m-%d %H:%M:%S’。可选。默认不过滤。
对象过滤
-d, –databases 只解析目标db的sql,多个库用空格隔开,如-d db1 db2。可选。默认为空。
-t, –tables 只解析目标table的sql,多张表用空格隔开,如-t tbl1 tbl2。可选。默认为空。
–only-dml 只解析dml,忽略ddl。可选。默认False。
–sql-type 只解析指定类型,支持INSERT, UPDATE, DELETE。多个类型用空格隔开,如–sql-type INSERT DELETE。可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。
四、binlog2sql 回滚数据
在对数据进行回滚时,一定要弄清楚误执行的sql语句和具体的时间,这对恢复数据可以提供很大的帮助
4.1 误删除数据-恢复
这里有一张工资表
1 | mysql> select * from payoff; |
由于操作失误对数据进行了 inster
,delete
,update
操作
1 | # 插入了一条新数据 |
此时表中最终的数据是
1 | mysql> select * from payoff; |
先查看最新的binlog位置
1 | mysql> show master logs; |
使用 binlog2sql 前,先创建一个专属用户
1 | mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO admin@"%" identified by "abc!@#123ABC"; |
用 binlog2sql 解析出标准SQL ,就是误操作的sql
1 | python3 binlog2sql.py -h192.168.126.133 -P3306 -uadmin -p'abc!@#123ABC' -dschool -t payoff --start-file='mysql-bin.000010' |
如果数据量大还可以根据
--start-datetime
起始时间和--stop-datetime
终止解析时间缩短范围
用 binlog2sql 解析出回滚SQL ,就多了一个 --flashback
参数
1 | # python3 binlog2sql.py --flashback -h192.168.126.133 -P3306 -uadmin -p'abc!@#123ABC' -dschool -t payoff --start-file='mysql-bin.000010' |
将需要回滚的反向sql重新执行一遍,就可以恢复数据了
1 | mysql> UPDATE `school`.`payoff` SET `id`=5, `name`='张丽丽', `age`=26, `sex`='女', `department`='运营', `salary`=6000 WHERE `id`=5 AND `name`='张丽丽' AND `age`=26 AND `sex`='女' AND `department`='运营' AND `salary`=10000 LIMIT 1; |
执行完恢复sql后,和之前的数据进行对比
1 | mysql> select * from payoff; |
4.2 误删除表-恢复
如果不小心删除了表,恢复步骤其实和上面是一样的
1 | mysql> delete from payoff; |
delete from table 是清空表数据,
drop table 是删除表结构和表数据,用binlog2sql无法恢复,只能通过数据库备份 + binlog来手动恢复
在实际使用中最好不要随便给用户授与drop权
先查看最新的binlog位置
1 | mysql> show master logs; |
用 binlog2sql 解析出标准SQL ,就是误操作的sql
1 | python3 binlog2sql.py -h192.168.126.133 -P3306 -uadmin -p'abc!@#123ABC' -dschool -t payoff --start-file='mysql-bin.000011' |
用 binlog2sql 解析出回滚SQL ,就多了一个 --flashback
参数
1 | python3 binlog2sql.py --flashback -h192.168.126.133 -P3306 -uadmin -p'abc!@#123ABC' -dschool -t payoff --start-file='mysql-bin.000011' |
将需要回滚的反向sql重新执行一遍,就可以恢复数据了
1 | mysql> INSERT INTO `school`.`payoff`(`id`, `name`, `age`, `sex`, `department`, `salary`) VALUES (6, '王芳', 28, '女', '人事', 5600); |