一般情况下,数据表被误操作,通常都会使用 备份+binlog 进行恢复。那如果误操作为dml而不是ddl,并且操作的语句不多,这样的话使用该方式会极大的影响业务,这就造成一个痛点:少量数据不恢复不行,恢复又极大的影响线上业务。这时binlog2sql应运而生,但是使用binlog2sql恢复会比较慢,这时Myflash 也就随之出现。具体应该使用哪一个下文会进行优缺点分析。
在此就不说明binlog是什么,怎么工作,内容的含义了(因为这是写给我自己看的-<->-)
每个工具实现闪回的方式都不同,但是有一点是一样的:
insert ----> delete ; delete -----> insert; update---->将set 和 where置换
binlog2sql是作为通过python-mysql-replication将自己作为伪slave读取binlog并将dml转换之后读取系统表TABLES,从而转换成标准的SQL语句。
myflash是直接解析binlog文件并将其转换,所以速度要快得多,使用此工具pos一定要找准。
到现在为止一般会有4种方法对binlog进行处理:
1.mysqlbinlog 工具配合 sed、awk
此方法比较简单,但是做起来还是比较复杂的,尤其是字段类型比较大的时候
2.给数据库源码打patch
mysql5.5的mysqlbinlog应该有flashback选项。这种方法需要对数据库源码非常熟悉并且善于编程的大佬。这种方法升级版本的话就不适用了,所以运维成本非常大。
3.binlog2sql
对SQL进行构造,稳定性好,上手难度低,效率也低。
4.myflash
前提:
MySQL server 必须设置以下参数:
[mysqld]
server_id=1
log_bin=/wx/mydata/mysql-bin.log
max_binlog_size=1G
binlog_format=row
binlog_row_image=full
1.版本
python2.7 , python 3.4+
mysql 5.6 、 5.7
2.安装python(2.7建议)
# wget https://www.python.org/downloads/release/python-371/Python-3.7.1.tgz
yum install libffi-devel openssl openssl-devel(去网上下载rpm包)
安装pip:略
3.下载binlog2sql
git clone https://github.com/danfengcao/binlog2sql.git
4.安装binlog2sql
sudo /usr/local/bin/pip install --no-index --find-links="./packages/" -r requirements.txt
packages可在https://download.csdn.net/download/wangxin3618/10883140 下载;也可自己制作
连网环境:pip install -r requirements.txt
pip安装:
python2.7 安装pip
1 先安装setuptools
下载地址:https://pypi.python.org/pypi/setuptools#downloads
将下载后的tar文件解压,用CMD模式进入到解压后的文件所在的目录执行命令:python setup.py install
2 安装pip
下载地址:https://pypi.python.org/pypi/pip#downloads
将下载后的tar文件解压,用CMD模式进入到解压后的文件所在的目录执行命令:python setup.py install
安装完成
使用:
1.DDL (truncate)语句,在整个过程中都是无法输出的
2.表删了,就不能解析出dml语句了,需将表创建后才能使用
3.文件可以是动态的(正在被追加的文件)
4.可解析大文件,不受内存限制。是否可以将一个binlog文件分成多个小文件处理???NO
5.mysql server 必须开启,离线(关闭)模式下不能解析
6.参数binlog_row_image 必须为full,暂不支持MINIMAL
7.解析速度不理想,不如myflash
8.纯python开发,安装使用很简单
9.自带flashback、no-primary-key解析模式,无需安装补丁
10.如果只回滚某张表,并且该表有关联表,关联表不会被回滚
用途:
1.数据快速回滚(闪回)
2.主从切换后新master丢数据的修复
3.从binlog生成标准SQL
binlog2sql解析原理:
通过binlog_dump 协议来获取binlog内容,需要读取information_schema.columns表来获取元信息,这样才能结合binlog拼接成SQL语句。所以给出用户的最小权限:GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'user'@'%';
权限说明:
select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
super/replication client:两个权限都可以,需要执行'SHOW MASTER STATUS', 获取server端的binlog列表
replication slave:通过BINLOG_DUMP协议获取binlog内容的权限
用python-mysql-replication实现了MySQL的复制协议,该服务伪装成mysql slave,来获取主的binlog和event。
如果在高并发环境上解析binlog,相当于多了一个同步线程在主上读取数据,这就加大了主的负担。
binlog2sql参数:
解析模式
--stop-never : 持续解析binlog。可选。默认false,同步至执行命令时最新的binlog位置,如果不ctrl+c就不会退出。
--no-primariy-key , -K : 对insert语句去除主键。可选。默认false
--flashback,-B : 生成回滚SQL,可解析大文件,不受内存限制。可选。默认false。与stop-never或no-primary-key 不能同时使用。
--back-interval -B 模式下,每打印一千行回滚SQL,加一句sleep多少秒,如果不想加sleep,请设为0.
解析范围控制
--start-file : 起始解析文件,只需要文件名,无需全路径。必须。
--stop-file : 终止解析文件,可选。默认和stat-file同一个文件。若解析模式为stop-server ,则该选项失效。
--start-position / --start-pos : 起始解析位置。可选,默认为start-file的起始位置
--stop-position / --stop-pos : 终止解析位置。可选。默认为stop-file的最末位置。若解析模式为stop-server ,则该选项失效。
--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 table1 table2 。可选默认为空
--only-dml 只解析dml,忽略ddl。可选默认false。在打印误删语句的时候会将ddl语句也打印出来,这时加上该选项则只打印dml。在flashback的时候不管加没加这个参数,都只打印dml。
--sql-type 只解析指定类型,支持insert,update,delete。多个类型用空格隔开:--sql-type insert delete .可选。默认dml都解析。用了此参数但没有填任何类型,则三者都不解析。在打印误操作语句的时候指定该参数则打印指定的类型如:指定insert就打印insert;在打印回滚语句的时候指定该参数则打印与之相反的类型如:指定insert,则打印delete;
使用方法:
首先判断误删语句所在的binlog文件:show master status; or 去binlog dir ll 查看binlog file的最后修改时间来确定
其次确定误删语句执行的大致时间:询问执行该语句的人
然后指定文件与时间和对应的库表做一次大致的筛选,然后再通过position筛选出需要回滚的数据(也可以查找binlog文件直接确定误操作语句的准确pos)
sudo python /wx/binlog2sql/binlog2sql/binlog2sql.py -uroot -h10.124.202.125 -p -P3306 --sql-type delete --only-dml -dtest -t table1 table2 --start-file='mysql-bin.000008' sudo python /wx/binlog2sql/binlog2sql/binlog2sql.py --flashback -uroot -h10.124.202.125 -p -P3306 --sql-type delete --only-dml -dtest -t table1 table2 --start-file='mysql-bin.000008' sudo python /wx/binlog2sql/binlog2sql/binlog2sql.py --flashback -uroot -h10.124.202.125 -p -P3306 --sql-type delete --only-dml -dtest -t table1 table2 --start-file='mysql-bin.000008'| mysql -uroot -h10.124.202.125 -p -P3306
安装依赖包
yum install gcc* pkg-config glib2 libgnomeui-devel -y
下载
git clone https://github.com/Meituan-Dianping/MyFlash.git
动态编译
gcc -w -g `pkg-config --cflags glib-2.0` source/binlogParseGlib.c -o binary/flashback /lib64/libglib-2.0.so.0
步骤:
1.首先flush logs;使误操作的binlog所在的log文件成为静态的
2.根据误操作的时间点和语句,通过mysqlbinlog |grep -i -C20 分析出误操作确定 的pos ;
3.然后生成回滚后的binlog
4.再将binlog导入到mysql server中
测试
mysql> flush logs;
shell> mysqlbinlog -vv --base64-output=decode-rows --start-datetime='2018-12-26 10:00:00' --database=test mysql-bin.000008|grep -i -C20 delete
shell> sudo ../binary/flashback --binlogFileNames=/wx/mydata/data1/binlog/mysql-bin.000008 --databaseNames=test --tableNames=table3 --sqlTypes='delete' --start-position=7955 --stop-position=8177
shell> sudo mysqlbinlog --skip-gtids binlog_output_base.flashback |/wx/mysql/bin/mysql -uroot -p -S /wx/mydata/data1/mysql.sock
测试问题:
1.在开启gtid的MySQL server上,应用flashback报错,错误为:ERROR 1782 (HY000) at line 16: @@SESSION.GTID_NEXT cannot be set to ANONYMOUS when @@GLOBAL.GTID_MODE = ON.
答:在导入时加入--skip-gtids mysqlbinlog --skip-gtids | mysql -uxxx -pxxx
2.如果回滚后的binlog日志尺寸超过20M,在导入时,很耗时。如何处理?
答:参考 使用 ,搜索maxSplitSize。使用该参数可以对文件进行切片
3.加入 sqlTypes ,会将原delete语句反转成insert语句
myflash 静态编译和动态编译:
动态编译链接
gcc -w `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c -o binary/flashback
然而用户不想每次去重新编译,可以选择使用静态链接,但是该方法需要知道glib库的版本和位置,因此对于每台机器略有不同,请谨慎使用
静态编译链接
为了保证在一台机器上编译后,可以在其它机器上使用,需要满足以下两个条件
a) 将glib做成静态链接
b)在编译的那台机器的glibc版本(查看方法为ldd --version)要小于等于要运行该软件的那台机器glibc版本 因此需要你在一台glibc版本较低的机器上运行如下命令即可。
gcc -w -g `pkg-config --cflags glib-2.0` source/binlogParseGlib.c -o binary/flashback /usr/lib64/libglib-2.0.a -lrt
使用:
1.解析的binlog文件需为静态的(解析过程中binlog不能再写入):尽量 flush logs 之后再分析
2.可以处理离线的binlog文件(该binlog文件对应的mysql server 可以是关闭的)
限制:
binlog格式必须为row,且binlog_row_image=full
仅支持5.6与5.7
只能回滚DML(增、删、改)
参数说明:
1.databaseNames
指定需要回滚的数据库名。多个可用‘,’隔开。不指定该参数则指定所有的库
2.tableNames
指定需要回滚的表名。多个可用‘,’隔开。不指定该参数则指定所有的表
3.start-position
指定回滚开始的位置,如不指定则从文件的开始处回滚
4.stop-position
指定回滚结束的位置,如不指定则回滚到文件结尾
5.start-datetime
指定回滚的开始时间,格式为 %Y-%m-%d %H:%M:%S。 如不指定,则不限定时间
6.stop-datetime
指定回滚的结束时间。注意格式必须是 %Y-%m-%d %H:%M:%S。 如不指定,则不限定时间
7.sqlTypes
指定需要回滚的sql类型。目前支持的过滤类型是INSERT, UPDATE ,DELETE。多个类型可以用“,”隔开。
8.maxSplitSize
一旦指定该参数,对文件进行固定尺寸的分割(单位为M)。防止单次应用的binlog尺寸过大。指定一个文件多少兆。
9.loglevel
仅开发者使用,默认级别为error级别。在生产环境中不要修改这个级别,窦泽会输出过多
10.include-gtids
指定需要回滚的gtid,支持gtid的单个和范围两种形式。
11.exclude-gtids
指定不需要回滚的gtid,用法同include-gtids
解析的不同:
与binlog2sql的解析方法不同:
binlog2sql:
1.binlog2sql 是先根据过滤条件将 操作的可视化语句 显示出来(每条语句后面包含该语句执行的时间与pos)
2.再根据pos将确定的语句回滚,将回滚后的语句导入到一个SQL文件,然后导入进mysql
flashback:
1.根据条件直接将binlog反转:可能反转出的不仅仅是误删的语句,这就需要查看原binlog文件确定误操作语句的准确pos。如果binlog文件很大,则查找很费力。但是binlog2sql解析很慢。
表:
CREATE TABLE `flash_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nameShort` varchar(20) DEFAULT NULL,
`nameLong` varchar(260) DEFAULT NULL,
`amount` decimal(19,9) DEFAULT NULL,
`amountFloat` float DEFAULT NULL,
`amountDouble` double DEFAULT NULL,
`createDatetime6` datetime(6) DEFAULT NULL,
`nameText` text,
`nameBlob` blob,
`nameMedium` mediumtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=876527 DEFAULT CHARSET=utf8
rows:100万; binlog文件大小:400M
生成反转语句:
myflash:binlog2sql = 1:8
将反转语句导入到mysql:
myflash:binlog2sql = 1:15
总结:从恢复速度上面 myflash 远优于 binlog2sql
myflash可处理离线binlog文件,并支持拆分,但是文件需是静态的
binlog2sql 可处理动态文件,但是server须存活