背景:
业务须要恢复一段时间内对某个表的全部DELETE记录,过滤UPDATE、INSERT操做,测试发现 MariaDB的flashback命令会闪回对表的全部dml操做,没法知足业务需求。调研三方工具测试发现binlog2sql能够实现生成原始SQL、回滚SQL、去除主键的INSERT SQL。
binlog2sql介绍:
由大众点评开源的一个 MySQL 闪回工具
用途
- 数据回滚
- 主从切换后数据不一致的修复
- 从 binlog 生成标准 SQL,带来的衍生功能
闪回原理简析
闪回原理,因为 MySQL binlog 以 event 为单位,记录数据库的变动信息,这些信息可以帮助咱们重现这之间的全部变化,也就是所谓的闪回。mysql
binlog 有三种可选的格式:git
- statement:基于 SQL 语句的模式,binlog 数据量小,可是某些语句和函数在复制过程可能致使数据不一致甚至出错;
- mixed:混合模式,根据语句来选用是 statement 仍是 row 模式;
- row:基于行的模式,记录的是行的完整变化。安全,但 binlog 会比其余两种模式大不少;
利用 binlog 作闪回,须要将 binlog 格式设置为 row,由于咱们须要最详尽的信息来肯定操做以后数据不会出错。github
既然 binlog 以 event 形式记录了全部的变动信息,那么咱们把须要回滚的 event,从后往前回滚回去便可sql
回滚操做:数据库
- 对于 delete 操做,咱们从 binlog 提取出 delete 信息,反向生成 insert 回滚语句;
- 对于 insert 操做,反向生成 delete 回滚语句;
- 对于 update 操做,根据信息生成反向的 update 语句;
- mysql 服务必须开启,离线模式下不能解析
- 参数 binlog_row_image 必须为FULL,暂不支持MINIMAL
- 解析速度不如mysqlbinlog
- 优势(对比mysqlbinlog)
- 纯Python开发,安装与使用都很简单
- 自带flashback、no-primary-key解析模式,无需再装补丁
- flashback模式下,更适合闪回实战
- 解析为标准SQL,方便理解、筛选
- 代码容易改造,能够支持更多个性化解析
官方测试环境:
Python2.七、3.4+
MySQL5.六、5.七、MariaDB 10.2.11(自测)
安装:
pip install -r requirements.txt
MySQL服务设置
binlog必须开启
binlog格式必须为row格式
binlog_row_image = full 由于须要解析具体行更新先后的变化,因此必须设置为full
链接用户权限:
select, super/replication client, replication slave
建议受权
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO
权限说明
select:须要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
super/replication client:两个权限均可以,须要执行'SHOW MASTER STATUS', 获取server端的binlog列表
replication slave:经过BINLOG_DUMP协议获取binlog内容的权限
基本用法:
解析标准SQL:
解析回滚SQL:
链接配置选项
mysql链接配置api
-h host; -P port; -u user; -p password安全
解析模式app
--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。可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。
测试
环境:Python2.7.8 MariaDB10.2.11
t1 表T1时刻 原始数据:
t1表T2时刻日后分别删除插入记录:
业务恢复需求:
将数据恢复至T1时刻,可是T1-T2这段时间的INSERT数据不须要恢复,只恢复DELETE的数据(即恢复id=2和3 的记录)
方法1:MariaDB flashback
/usr/local/mariadb/bin/mysqlbinlog --start-datetime='2019-06-05 18:49:37' -d test -T t1 hf_test-bin.000131 --flashback >recover.sql
能够生成对应的回滚语句,可是包含此表这段时间的全部dml操做,单纯过滤出DELETE操做出错率高,可靠性差
方法2:binlog2sql
解析这段时间对此表的dml操做
生成回滚SQL
过滤文件中业务须要的INSERT语句:
恢复:myin 3308 test <./insert.sql
T1后插入的 dd ,ee 记录保留,删除的bb,cc 恢复完成!
总结:
业务方会根据各类场景提各类奇葩需求,须要DBA根据具体状况具体分析,多测试,才能作到驾轻就熟
MariaDB的flashback颇有效,但针对此需求binlog2sql更适合,具体需求具体分析