binlog2sql之MySQL数据闪回

DBA或开发人员,有时会误删或者误更新数据,如果是线上环境并且影响较大,就需要能快速回滚。传统恢复方法是利用备份重搭实例,再应用去除错误sql后的binlog来恢复数据。此法费时费力,甚至需要停机维护,并不适合快速回滚。也有团队利用LVM快照来缩短恢复时间,但快照的缺点是会影响mysql的性能。现在有不少好用而且效率又高的开源闪回工具如binlog2sql、mysqlbinlog_flashback,这些工具在工作中给DBA减轻了不少痛苦,以下针对binlog2sql的使用进行实践演练。

binlog2sql的用途:

  • 数据快速回滚(闪回)
  • 主从切换后数据不一致的修复
  • 从binlog生成标准SQL,带来的衍生功能

安装binlog2sql前先安装git和pip:

yum -y install epel-release 
yum -y install git  python-pip
git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
pip install -r requirements.txt

MySQL的配置要开启以下选项:

mysqld]
server_id = 1log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1G
binlog_format = row
binlog_row_image = full

要授权一个用户有以下权限:

SELECT, REPLICATION SLAVE, REPLICATION CLIENT

权限说明:

  • select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
  • super/replication client:两个权限都可以,需要执行‘SHOW MASTER STATUS‘, 获取server端的binlog列表
  • replication slave:通过BINLOG_DUMP协议获取binlog内容的权限

binlog2sql的使用参数说明:

mysql连接配置

-h host; -P port; -u user; -p password

解析模式

--stop-never 持续同步binlog。可选。不加则同步至执行命令时最新的binlog位置。

-K, --no-primary-key 对INSERT语句去除主键。可选。

-B, --flashback 生成回滚语句,可解析大文件,不受内存限制,每打印一千行加一句SLEEP SELECT(1)。可选。与stop-never或no-primary-key不能同时添加。

解析范围控制

--start-file 起始解析文件。必须。

--start-position/--start-pos start-file的起始解析位置。可选。默认为start-file的起始位置。

--stop-file/--end-file 末尾解析文件。可选。默认为start-file同一个文件。若解析模式为stop-never,此选项失效。

--stop-position/--end-pos stop-file的末尾解析位置。可选。默认为stop-file的最末位置;若解析模式为stop-never,此选项失效。

--start-datetime 从哪个时间点的binlog开始解析,格式必须为datetime,如‘2016-11-11 11:11:11‘。可选。默认不过滤。

--stop-datetime 到哪个时间点的binlog停止解析,格式必须为datetime,如‘2016-11-11 11:11:11‘。可选。默认不过滤。

对象过滤

-d, --databases 只输出目标db的sql。可选。默认为空。

-t, --tables 只输出目标tables的sql。可选。默认为空。

进行用户授权操作(这里只是举例子):

mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO  ‘flashuser‘@‘127.0.0.1‘ identified by ‘flash123‘;
Query OK, 0 rows affected (0.00 sec)

我们可以看看现在有的数据:

mysql>  show global variables like ‘binlog_format‘;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
row in set (0.00 sec)

mysql>

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000107 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
row in set (0.00 sec)

mysql> select * from tb1;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    2 | bb   |
+------+------+
rows in set (0.00 sec)

mysql>

我们现在进行数据的DML操作:

mysql>  insert into tb1 values (3,‘cc‘);
Query OK, 1 row affected (0.00 sec)

mysql>  insert into tb1 values (4,‘dd‘);
Query OK, 1 row affected (0.00 sec)

mysql>  update tb1 set name=‘new_aa‘ where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql>  delete from tb1 where id=2;
Query OK, 1 row affected (0.00 sec)

mysql>  select * from tb1;
+------+--------+
| id   | name   |
+------+--------+
|    1 | new_aa |
|    3 | cc     |
|    4 | dd     |
+------+--------+
rows in set (0.00 sec)

mysql>

下面我们使用binlog2sql进行格式为ROW的binlog生成标准SQL,带个-d的参数指定库名:

[[email protected]_server ~]#python binlog2sql.py -uflashuser -h127.0.0.1 -pflash123 -dxuanzhi --start-file=‘mysql-bin.000107‘ > xuanzhi.sql 
[[email protected]_server ~]#cat xuanzhi.sql 
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (3, ‘cc‘); #start 4 end 290 time 2017-03-23 10:41:34
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (4, ‘dd‘); #start 321 end 491 time 2017-03-23 10:41:38
UPDATE `xuanzhi`.`tb1` SET `id`=1, `name`=‘new_aa‘ WHERE `id`=1 AND `name`=‘aa‘ LIMIT 1; #start 522 end 705 time 2017-03-23 10:41:42
DELETE FROM `xuanzhi`.`tb1` WHERE `id`=2 AND `name`=‘bb‘ LIMIT 1; #start 736 end 906 time 2017-03-23 10:41:50
[[email protected]_server ~]#

我们可以看到,刚刚执行过的sql都生成出来了。

我们现在对xuanzhi这个库的所有操作生成反向SQL,这个时候需要在上面语句的基础上带一个-B参数,就是flashback闪回的意思:

[[email protected]_server ~]#python binlog2sql.py -uflashuser -h127.0.0.1 -pflash123 -dxuanzhi --start-file=‘mysql-bin.000107‘ > xuanzhi.sql 
[[email protected]_server ~]#cat xuanzhi.sql 
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (3, ‘cc‘); #start 4 end 290 time 2017-03-23 10:41:34
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (4, ‘dd‘); #start 321 end 491 time 2017-03-23 10:41:38
UPDATE `xuanzhi`.`tb1` SET `id`=1, `name`=‘new_aa‘ WHERE `id`=1 AND `name`=‘aa‘ LIMIT 1; #start 522 end 705 time 2017-03-23 10:41:42
DELETE FROM `xuanzhi`.`tb1` WHERE `id`=2 AND `name`=‘bb‘ LIMIT 1; #start 736 end 906 time 2017-03-23 10:41:50
[[email protected]_server ~]#

我们可以看到,刚刚执行过的sql都生成出来了。

我们现在对xuanzhi这个库的所有操作生成反向SQL,这个时候需要在上面语句的基础上带一个-B参数,就是flashback闪回的意思:

[[email protected]_server ~]#python binlog2sql.py -uflashuser -h127.0.0.1 -pflash123 -dxuanzhi --start-file=‘mysql-bin.000107‘ -B  > rollback_xuanzhi.sql
[[email protected]_server ~]#cat rollback_xuanzhi.sql 
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (2, ‘bb‘); #start 736 end 906 time 2017-03-23 10:41:50
UPDATE `xuanzhi`.`tb1` SET `id`=1, `name`=‘aa‘ WHERE `id`=1 AND `name`=‘new_aa‘ LIMIT 1; #start 522 end 705 time 2017-03-23 10:41:42
DELETE FROM `xuanzhi`.`tb1` WHERE `id`=4 AND `name`=‘dd‘ LIMIT 1; #start 321 end 491 time 2017-03-23 10:41:38
DELETE FROM `xuanzhi`.`tb1` WHERE `id`=3 AND `name`=‘cc‘ LIMIT 1; #start 4 end 290 time 2017-03-23 10:41:34
[[email protected]_server_xuanzhi ~]#

可以看到生成了跟上面标准SQL相反的SQL了,通过这些反向SQL可以进行误操的数据恢复。

下面我们模拟对线上数据进行误操及恢复的过程:

模拟一:误操把一个表的某些重要记录删除了,进行恢复

我们把tb1的id>=3的数据删除:

mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
|  3 | cc   |
|  4 | dd   |
+----+------+
rows in set (0.00 sec)

mysql> delete from tb1 where id >= 3;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from tb1;            
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
rows in set (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000109 |      329 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

现在通过binlog2sql进行生成反向SQL,binlog2sql可以指定生成那个库的那个表的标准SQL或者反向SQL,带一个-t的选择:

[[email protected]_server ~]# python binlog2sql.py -uflashuser -h127.0.0.1 -pflash123 -dxuanzhi -ttb1 --start-file=‘mysql-bin.000109‘ -B  > rollback_tb1.sql 
[[email protected]_server ~]# cat rollback_tb1.sql 
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (4, ‘dd‘); #start 4 end 298 time 2017-03-23 12:39:20INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (3, ‘cc‘); #start 4 end 298 time 2017-03-23 12:39:20

我们可以看刚刚对tb1进行误删的操作,都生成了反向的SQL语句也就是INSERT INTO,我们进行导入操作,看数据能否正常恢复

[[email protected]_server_xuanzhi ~]#mysql -uroot -p123456 <./rollback_tb1.sql 
Warning: Using a password on the command line interface can be insecure.
[[email protected]_server_xuanzhi ~]#

登录查看一下数据:

mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
|  3 | cc   |
|  4 | dd   |
+----+------+
rows in set (0.00 sec)

mysql>

可以看到数据可以正常的恢复。

模拟二:误操作把一个表的数据删除了,经常出现的就是delete没带where条件

mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
|  3 | cc   |
|  4 | dd   |
+----+------+
rows in set (0.00 sec)

mysql> delete from tb1;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from tb1;
Empty set (0.00 sec)

mysql> show master status;           
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000110 |      345 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
row in set (0.00 sec)

mysql>

我们用bin2log对这个表进行恢复:

[[email protected]_server ~]# python binlog2sql.py -uflashuser -h127.0.0.1 -pflash123 -dxuanzhi -ttb1 --start-file=‘mysql-bin.000110‘ -B  > rollback_tb1.sql  
[[email protected]_server ~]# cat rollback_tb1.sql 
INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (4, ‘dd‘); #start 4 end 314 time 2017-03-23 13:37:29INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (3, ‘cc‘); #start 4 end 314 time 2017-03-23 13:37:29INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (2, ‘bb‘); #start 4 end 314 time 2017-03-23 13:37:29INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (1, ‘aa‘); #start 4 end 314 time 2017-03-23 13:37:29[[email protected]_server_xuanzhi ~]# mysql -uroot -p123456 <./rollback_tb1.sql                                                                   
Warning: Using a password on the command line interface can be insecure.

再查询一下,数据是否把数据恢复了:

mysql> select * from tb1;
Empty set (0.00 sec)<Slave_1>[xuanzhi]> show master status;           
+------------------+----------+--------------+------------------+-------------------+| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+------------------+----------+--------------+------------------+-------------------+| mysql-bin.000110 |      345 |              |                  |                   |+------------------+----------+--------------+------------------+-------------------+1 row in set (0.00 sec)

mysql> select * from tb1; 
+----+------+| id | name |+----+------+|  1 | aa   ||  2 | bb   ||  3 | cc   ||  4 | dd   |+----+------+4 rows in set (0.00 sec)

mysql>

可以看到可以正常恢复,但值得注意的是drop table 和truncate table 是无法生成反向SQL的,所以建议线上程序账号只给insert,upfate,select,delete权限。

还有很多选项--stop-position/--end-pos stop-file、--start-datetime/--stop-datetime这些选项就不一 一说明了,binlog2sql总的来说还是比较好用与实用的,以前写过一篇博客binlog-rollback.pl  的博客,这个脚本也可以实现,但遇到比较大的binlog就可能会出现一些问题,下面是我在线上测试对1.1G的binlog用binlog2sql进行解析的时间(阿里云的SSD盘):

参考文章:

https://github.com/danfengcao/binlog2sql

https://github.com/danfengcao/binlog2sql/blob/master/example/mysql-flashback-priciple-and-practice.md

总结:一、线上要对程序做好最小化权限控制,这样可以减少很多不必要的麻烦。

二、现在开源比较好用的数据闪回工具有mysqlbinlog_flashbackbinlog2sql,给DBA日常维护带来了许多帮助。

时间: 2024-10-21 15:04:44

binlog2sql之MySQL数据闪回的相关文章

Mysql数据闪回的奇技淫巧(binlog2sql)

一.概述 binlog2sql是一个开源项目,应用于大众点评线上环境.类似于ORACLE中的闪回功能,binlog2sql可以基于时间点或者位置偏移量进行数据恢复.从MySQL binlog解析出你要的SQL.根据不同选项,你可以得到原始SQL.回滚SQL.去除主键的INSERT SQL等.也就是对于insert操作会生成对应的delete语句,反之delete操作会生出对应的insert语句,update操作会生成相反的语句. 关于binlog2sql的闪回详细介绍可参考闪回原理与实战.我也是

MySQL Flashback 闪回功能详解

阅读目录 1. 简介 2. 闪回原理 3. flashback安装 4. 使用简介 5. Flashback工具使用注意点 回到顶部 1. 简介 mysqlbinlog flashback(闪回)用于快速恢复由于误操作丢失的数据.在DBA误操作时,可以把数据库恢复到以前某个时间点(或者说某个binlog的某个pos).比如忘了带where条件的update.delete操作,传统的恢复方式是利用全备+二进制日志前滚进行恢复,相比于传统的全备+增备,flashback显然更为快速.简单. 目前My

oracle flashback——oracle数据闪回实战,及恢复数据到指定的时间戳——timestamp

Microsoft Windows [版本 6.1.7601] 版权所有 (c) 2009 Microsoft Corporation.保留所有权利. C:\Users\ckz>sqlplus zzjd/[email protected]/orcl as sysdba; SQL*Plus: Release 11.2.0.1.0 Production on 星期三 5月 13 17:00:46 2015 Copyright (c) 1982, 2010, Oracle. All rights re

mysql&quot;闪回&quot;技术恢复误删除误更改的数据

相信很多人都遇到过忘带where条件或者where条件漏写了一个和写错了的情况,结果执行了delete/update后把整张表的数据都给改了.传统的解决方法是:利用最近的全量备份+增量binlog备份,恢复到误操作之前的状态,但是此方法有一个弊端,那就是随着表的记录增大,binlog的增多,恢复起来会很费时费力. 现在有一个简单的方法,可以恢复到误操作之前的状态.听起来这方法似乎利用的是Oracle的闪回功能,但MySQL目前(包括最新的V5.7版本与MariaDB10.1分支版本)还不具有这样

Oracle闪回技术详解

概述: 闪回技术是Oracle强大数据库备份恢复机制的一部分,在数据库发生逻辑错误的时候,闪回技术能提供快速且最小损失的恢复(多数闪回功能都能在数据库联机状态下完成).需要注意的是,闪回技术旨在快速恢复逻辑错误,对于物理损坏或是介质丢失的错误,闪回技术就回天乏术了,还是得借助于Oracle一些高级的备份恢复工具如RAMN去完成(这才是Oracle强大备份恢复机制的精髓所在啊)  撤销段(UNDO SEGMENT) 在讲闪回技术前,需要先了解Oracle中一个逻辑结构--撤销段.因为大部分闪回技术

oracle闪回查询和闪回数据库

oracle闪回查询和闪回数据库 区别: 数据闪回查询,只需要启用撤销表空间自动管理回滚信息. 使用闪回删除技术和闪回数据库技术,需要启动回收站,闪回恢复区.(归档模式使用) 具体设置: ---cmd sqlplus nolog sys as sysdba hanatech 具体设置----数据闪回查询的设置: 查看撤销表信息undo: show parameter undo; 设置撤销表信息: alter system set undo_managerment=auto;设置为auto才可以使

Oracle学习(15)【DBA向】:闪回

闪回Flashback 什么是闪回 l在Oracle的操作工程中,会不可避免地出现操作失误或者用户失误,例如不小心删除了一个表等,这些失误和错误可能会造成重要数 据的丢失,最终导致Oracle数据库停止. l在传统意义上,当发生数据丢失.数据错误问题时,解决的主要办法是数据的导入导出.备份恢复技术,这些方法都需要在发生错误 前,有一个正确的备份才能进行恢复. l为了减少这方面的损失,Oracle提供了闪回技术.有了闪回技术,就可以实现数据的快速恢复,而且不需要数据备份. 闪回的好处 恢复中,闪回

专题实验 oracle 闪回特性

在 oracle 9i 之前的版本中, 如果用户因为误操作 delete 或 update 并提交了, 那么恢复这些用户的操作错误是极其低效的. 为此, oracle 提供了闪回功能, 通过回退, 我们可以找回正确的数据. oracle 闪回查询特性 通过闪回查询我们可以按照时间戳或SCN来向前查询, 获取修改之前的数据镜像, 再通过insert等操作就可以恢复数据. 闪回查询一来于回滚段中存储的数据前镜像, 在oracle9i以前的版本中, 通常只要事务提交后, 前镜像数据就可以被覆盖, 空间

【oracle11g,13】表空间管理2:undo表空间管理(调优) ,闪回原理

一.undo空间原理: dml操作会产生undo数据. update时,sever process 会在databuffer 中找到该记录的buffer块,没有就从datafile中找并读入data buffer.在修改之前,原始数据先放到undo段,并在数据块头记录undo段(acitve 状态)中该数据块的位置,读写这个块时会占用事务槽,会将该事务号记录在数据块的头部.然后在进行update,并将该块放到dirty list检查点队列,等待dbwr进行写操作. 二.创建新的undo表空间替换