binlog2sql是一个开源的Python开发的MySQL Binlog解析工具,能够将Binlog解析为原始的SQL,也支持将Binlog解析为回滚的SQL,以便做数据恢复。
主要功能:
- 将Binlog解析为SQL语句
- 将Binlog解析为回滚的SQL语句
开源地址:
github.com/danfengcao/binlog2sql
支持的版本:
- Python 2.7, 3.4+
- MySQL 5.6, 5.7
外部依赖包:
下载源码,打开源码目录中的requirements.txt文件,即可看到依赖的外部包,如下:
- PyMySQL==0.7.11
- wheel==0.29.0
- mysql-replication==0.13
通过执行如下命令,安装外部依赖包。
shell> pip install -r requirements.txt
MySQL Server的配置:
MySQL的配置,必须满足以下要求,才能正常使用binlog2sql工具。开启binlog,binlog格式必须为ROW,且binlog_row_image必须为full。
[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1G
binlog_format = row
binlog_row_image = full
binlog2sql参数选项:mysql连接选项,与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。可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。
使用案例:
案例一:解析binlog,生成正向的sql语句。
[root@localhost binlog2sql]# python2.7 binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'123456' --start-file='mysql-bin.000001' --stop-file='mysql-bin.000001'
USE db;
create database db;
USE db;
create table tb(id int);
INSERT INTO `db`.`tb`(`id`) VALUES (100); #start 530 end 683 time 2019-09-25 11:28:26
INSERT INTO `db`.`tb`(`id`) VALUES (1); #start 779 end 925 time 2019-09-25 11:31:15
USE db;
create table tb1(id int);
在没有加 --only-dml 参数的情况下,会连ddl语句也解析出来,加上 --only-dml 参数,看到只解析dml语句。
[root@localhost binlog2sql]# python2.7 binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'123456' --start-file='mysql-bin.000001' --stop-file='mysql-bin.000001' --only-dml
INSERT INTO `db`.`tb`(`id`) VALUES (100); #start 530 end 683 time 2019-09-25 11:28:26
INSERT INTO `db`.`tb`(`id`) VALUES (1); #start 779 end 925 time 2019-09-25 11:31:15
案例二:解析binlog,生成回滚的sql语句。
[root@localhost binlog2sql]# python2.7 binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'123456' --start-file='mysql-bin.000001' --stop-file='mysql-bin.000001' --flashback
DELETE FROM `db`.`tb` WHERE `id`=1 LIMIT 1; #start 779 end 925 time 2019-09-25 11:31:15
DELETE FROM `db`.`tb` WHERE `id`=100 LIMIT 1; #start 530 end 683 time 2019-09-25 11:28:26
加上--flashback参数,即可生成回滚的sql。回滚sql是正向sql的反转,insert 100, insert 1, 反转后,变为 delete 1, delete 100。
问题:
binlog2sql解析binlog依赖于第三方开源库python-mysql-replication,这个开源库在解析不规范的时间、日期格式时会有问题,比如timestamp类型的字段,如果值为'0000-00-00 00:00:00'时,解析结果为
'1970-01-01 08:00:00',这个值无法插入到MySQL中。这样的问题很早就有人提出来了,但是官方一直拒绝修复,可能官方认为'0000-00-00 00:00:00'这样的时间戳本来就是无效的,不需要处理这样无效的值,应该修改mysql的sql_mode来避免出现这种不规范的值。
总结:
binlog2sql 安装使用方便,源码文件不多,也不大,但是功能非常强大。需要注意的是,在使用binlog2sql时,mysql server必须开启,离线模式下不能解析。