binlog-rollback.pl 在线恢复update 和delete不加条件误操作sql

一、binlog-rollback.pl工具介绍

是perl开发的脚本工具,此工具主要是生成反向的DML sql语句:

#基于row模式的binlog,生成DML(insert/update/delete)的rollback语句
#通过mysqlbinlog -v 解析binlog生成可读的sql文件
#提取需要处理的有效sql
#"### "开头的行.如果输入的start-position位于某个event group中间,则会导致"无法识别event"错误

#将INSERT/UPDATE/DELETE 的sql反转,并且1个完整sql只能占1行
#INSERT: INSERT INTO => DELETE FROM, SET => WHERE
#UPDATE: WHERE => SET, SET => WHERE
#DELETE: DELETE FROM => INSERT INTO, WHERE => SET
#用列名替换位置@{1,2,3}
#通过desc table获得列顺序及对应的列名
#特殊列类型value做特别处理
#逆序

#注意:

#表结构与现在的表结构必须相同[谨记]
#由于row模式是幂等的,并且恢复是一次性,所以只提取sql,不提取BEGIN/COMMIT
#只能对INSERT/UPDATE/DELETE进行处理
#线上误操作后,一定要立刻对操作的表进行加锁,避免其他数据继续写入

二、MySQL server必须设置以下参数:

cat /etc/my.cnf

[client]
port = 3306
socket = /tmp/mysql.sock
default-character-set=utf8

[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1G
binlog_format = row
binlog_row_image = full
character-set-server = utf8

三、此工具使用需要创建一个mysql的管理用户来操作

不建议直接使用mysql的root账户来操作,建议授权一个最小权限的用户来操作
登录mysql创建最小的授权用户admin
user需要的最小权限集合:

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内容的权限

MySQL [(none)]> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO [email protected]‘127.0.0.1‘ identified by ‘admin‘;

四、binlog-rollback.pl工具参数介绍

[[email protected] opt]# perl binlog-rollback.pl -help
<Error>:please input binlog file
==========================================================================================
Command line options :
    --help              # OUT : print help info
    -f, --srcfile           # IN  : binlog file. [required]
    -o, --outfile           # OUT : output sql file. [required]
    -h, --host          # IN  : host. default ‘127.0.0.1‘
    -u, --user          # IN  : user. [required]
    -p, --password          # IN  : password. [required]
    -P, --port          # IN  : port. default ‘3306‘
    --start-datetime        # IN  : start datetime
    --stop-datetime         # IN  : stop datetime
    --start-position        # IN  : start position
    --stop-position         # IN  : stop position
    -d, --database          # IN  : database, split comma
    -T, --table         # IN  : table, split comma. [required] set -d
    -i, --ignore            # IN  : ignore binlog check contain DDL(CREATE|ALTER|DROP|RENAME)
    --debug             # IN  :  print debug information

Sample :
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ -i
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ --debug
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -h ‘192.168.1.2‘ -u ‘user‘ -p ‘pwd‘ -P 3307
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ --start-position=107
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ --start-position=107 --stop-position=10000
   shell> perl binlog-rollback.pl -f ‘mysql-bin.000001‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ -d ‘db1,db2‘
   shell> perl binlog-rollback.pl -f ‘mysql-bin.0000*‘ -o ‘/tmp/t.sql‘ -u ‘user‘ -p ‘pwd‘ -d ‘db1,db2‘ -T ‘tb1,tb2‘

操作报错如下:

[[email protected] opt]#  perl binlog-rollback.pl -f ‘/data/mysql/data/mysql-bin.000002‘ -o ‘/tmp/t.sql‘ -u ‘admin‘ -p ‘admin‘
mysqlbinlog: unknown variable ‘default-character-set=utf8‘
mysqlbinlog: unknown variable ‘default-character-set=utf8‘
mysqlbinlog: unknown variable ‘default-character-set=utf8‘

解决办法:

[[email protected] opt]# grep mysqlbinlog binlog-rollback.pl
#通过mysqlbinlog -v 解析binlog生成可读的sql文件
    $MYSQLBINLOG = qq{mysqlbinlog --no-defaults -v}; ###添加上参数--no-defaults  解决问题

五、测试delete,和update误操作后的sql语提取和数据的恢复

5.1delete删除忘记添加条件恢复测试

MySQL [zixun3]> select *  from zx_scores;
+----+--------+------+----------+-----------+
| id | titles | icon | integral | isdefault |
+----+--------+------+----------+-----------+
|  2 | 列兵   |    1 |        0 |         1 |
|  3 | 班长   |    2 |     1000 |         1 |
|  4 | 少尉   |    3 |     2000 |         1 |
|  5 | 中尉   |    4 |     3000 |         1 |
|  6 | 上尉   |    5 |     4000 |         1 |
|  7 | 少校   |    6 |     5000 |         1 |
|  8 | 中校   |    7 |     6000 |         1 |
|  9 | 上校   |    8 |     9000 |         1 |
| 10 | 少将   |    9 |    14000 |         1 |
| 11 | 中将   |   10 |    19000 |         1 |
| 12 | 上将   |   11 |    24000 |         1 |
| 15 | 大将   |   12 |    29000 |         1 |
+----+--------+------+----------+-----------+
12 rows in set (0.00 sec)

MySQL [zixun3]> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000003
         Position: 592
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

MySQL [zixun3]> flush logs;
Query OK, 0 rows affected (0.10 sec)

MySQL [zixun3]> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000004
         Position: 120
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

delete删除时,不加任何条件,导致误删除

MySQL [zixun3]> delete  from zx_scores;
Query OK, 12 rows affected (0.00 sec)

MySQL [zixun3]> 

[[email protected] opt]#  perl binlog-rollback.pl -f ‘/data/mysql/data/mysql-bin.000004‘ -o ‘/tmp/insert.sql‘ -u ‘admin‘ -p ‘admin‘ -h 127.0.0.1 -i
Warning: Using a password on the command line interface can be insecure.

[[email protected] opt]# cat /tmp/insert.sql
INSERT INTO `zixun3`.`zx_scores` SET `id`=15, `titles`=‘大将‘, `icon`=12, `integral`=29000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=12, `titles`=‘上将‘, `icon`=11, `integral`=24000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=11, `titles`=‘中将‘, `icon`=10, `integral`=19000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=10, `titles`=‘少将‘, `icon`=9, `integral`=14000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=9, `titles`=‘上校‘, `icon`=8, `integral`=9000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=8, `titles`=‘中校‘, `icon`=7, `integral`=6000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=7, `titles`=‘少校‘, `icon`=6, `integral`=5000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=6, `titles`=‘上尉‘, `icon`=5, `integral`=4000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=5, `titles`=‘中尉‘, `icon`=4, `integral`=3000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=4, `titles`=‘少尉‘, `icon`=3, `integral`=2000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=3, `titles`=‘班长‘, `icon`=2, `integral`=1000, `isdefault`=1;
INSERT INTO `zixun3`.`zx_scores` SET `id`=2, `titles`=‘列兵‘, `icon`=1, `integral`=0, `isdefault`=1;

MySQL [zixun3]> source /tmp/insert.sql

MySQL [zixun3]> select *  from zx_scores;
+----+--------+------+----------+-----------+
| id | titles | icon | integral | isdefault |
+----+--------+------+----------+-----------+
|  2 | 列兵   |    1 |        0 |         1 |
|  3 | 班长   |    2 |     1000 |         1 |
|  4 | 少尉   |    3 |     2000 |         1 |
|  5 | 中尉   |    4 |     3000 |         1 |
|  6 | 上尉   |    5 |     4000 |         1 |
|  7 | 少校   |    6 |     5000 |         1 |
|  8 | 中校   |    7 |     6000 |         1 |
|  9 | 上校   |    8 |     9000 |         1 |
| 10 | 少将   |    9 |    14000 |         1 |
| 11 | 中将   |   10 |    19000 |         1 |
| 12 | 上将   |   11 |    24000 |         1 |
| 15 | 大将   |   12 |    29000 |         1 |
+----+--------+------+----------+-----------+
12 rows in set (0.00 sec)

delete操作恢复完成

5.2update更新时忘记加条件限制的数据恢复

MySQL [zixun3]> update zx_scores set titles=‘班长‘;
Query OK, 11 rows affected (0.00 sec)
Rows matched: 12  Changed: 11  Warnings: 0

MySQL [zixun3]> select *  from zx_scores;
+----+--------+------+----------+-----------+
| id | titles | icon | integral | isdefault |
+----+--------+------+----------+-----------+
|  2 | 班长   |    1 |        0 |         1 |
|  3 | 班长   |    2 |     1000 |         1 |
|  4 | 班长   |    3 |     2000 |         1 |
|  5 | 班长   |    4 |     3000 |         1 |
|  6 | 班长   |    5 |     4000 |         1 |
|  7 | 班长   |    6 |     5000 |         1 |
|  8 | 班长   |    7 |     6000 |         1 |
|  9 | 班长   |    8 |     9000 |         1 |
| 10 | 班长   |    9 |    14000 |         1 |
| 11 | 班长   |   10 |    19000 |         1 |
| 12 | 班长   |   11 |    24000 |         1 |
| 15 | 班长   |   12 |    29000 |         1 |
+----+--------+------+----------+-----------+
12 rows in set (0.00 sec)
[[email protected] opt]#  perl binlog-rollback.pl -f ‘/data/mysql/data/mysql-bin.000004‘ -o ‘/tmp/update.sql‘ -u ‘admin‘ -p ‘admin‘ -h 127.0.0.1 -i
Warning: Using a password on the command line interface can be insecure.

由于mysql-bin.000004 中记录了所有的sql域名,而且binlog-rollback.pl 次工具是过滤mysql-bin.000004 中所有的DML语句 insert,update,delete,所以需要把单独的update语句过滤出来

[[email protected] opt]# grep -i update /tmp/update.sql >/tmp/3.sql
[[email protected] opt]# cat /tmp/3.sql
UPDATE `zixun3`.`zx_scores` SET `id`=15, `titles`=‘大将‘, `icon`=12, `integral`=29000, `isdefault`=1 WHERE `id`=15 AND `titles`=‘班长‘ AND `icon`=12 AND `integral`=29000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=12, `titles`=‘上将‘, `icon`=11, `integral`=24000, `isdefault`=1 WHERE `id`=12 AND `titles`=‘班长‘ AND `icon`=11 AND `integral`=24000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=11, `titles`=‘中将‘, `icon`=10, `integral`=19000, `isdefault`=1 WHERE `id`=11 AND `titles`=‘班长‘ AND `icon`=10 AND `integral`=19000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=10, `titles`=‘少将‘, `icon`=9, `integral`=14000, `isdefault`=1 WHERE `id`=10 AND `titles`=‘班长‘ AND `icon`=9 AND `integral`=14000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=9, `titles`=‘上校‘, `icon`=8, `integral`=9000, `isdefault`=1 WHERE `id`=9 AND `titles`=‘班长‘ AND `icon`=8 AND `integral`=9000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=8, `titles`=‘中校‘, `icon`=7, `integral`=6000, `isdefault`=1 WHERE `id`=8 AND `titles`=‘班长‘ AND `icon`=7 AND `integral`=6000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=7, `titles`=‘少校‘, `icon`=6, `integral`=5000, `isdefault`=1 WHERE `id`=7 AND `titles`=‘班长‘ AND `icon`=6 AND `integral`=5000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=6, `titles`=‘上尉‘, `icon`=5, `integral`=4000, `isdefault`=1 WHERE `id`=6 AND `titles`=‘班长‘ AND `icon`=5 AND `integral`=4000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=5, `titles`=‘中尉‘, `icon`=4, `integral`=3000, `isdefault`=1 WHERE `id`=5 AND `titles`=‘班长‘ AND `icon`=4 AND `integral`=3000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=4, `titles`=‘少尉‘, `icon`=3, `integral`=2000, `isdefault`=1 WHERE `id`=4 AND `titles`=‘班长‘ AND `icon`=3 AND `integral`=2000 AND `isdefault`=1;
UPDATE `zixun3`.`zx_scores` SET `id`=2, `titles`=‘列兵‘, `icon`=1, `integral`=0, `isdefault`=1 WHERE `id`=2 AND `titles`=‘班长‘ AND `icon`=1 AND `integral`=0 AND `isdefault`=1;

MySQL [zixun3]> source //tmp/3.sql ;
MySQL [zixun3]> select *  from zx_scores;
+----+--------+------+----------+-----------+
| id | titles | icon | integral | isdefault |
+----+--------+------+----------+-----------+
|  2 | 列兵   |    1 |        0 |         1 |
|  3 | 班长   |    2 |     1000 |         1 |
|  4 | 少尉   |    3 |     2000 |         1 |
|  5 | 中尉   |    4 |     3000 |         1 |
|  6 | 上尉   |    5 |     4000 |         1 |
|  7 | 少校   |    6 |     5000 |         1 |
|  8 | 中校   |    7 |     6000 |         1 |
|  9 | 上校   |    8 |     9000 |         1 |
| 10 | 少将   |    9 |    14000 |         1 |
| 11 | 中将   |   10 |    19000 |         1 |
| 12 | 上将   |   11 |    24000 |         1 |
| 15 | 大将   |   12 |    29000 |         1 |
+----+--------+------+----------+-----------+
12 rows in set (0.00 sec)

完成恢复

简单吧,同时此工具还可以结合位置点和时间点进行恢复,请关注后面的博文。

原文地址:http://blog.51cto.com/wujianwei/2119063

时间: 2024-08-02 02:23:35

binlog-rollback.pl 在线恢复update 和delete不加条件误操作sql的相关文章

delete、update忘加where条件误操作恢复过程演示

update.delete没有带where条件,误操作,如何恢复呢? 我现在有一张学生表,我要把小于60更新成不及格. 1 mysql> select * from student; 2 3 +----+------+-------+-------+ 4 5 | id | name | class | score | 6 7 +----+------+-------+-------+ 8 9 | 1 | a | 1 | 56 | 10 11 | 2 | b | 1 | 61 | 12 13 |

MySQL 误操作后数据恢复(update,delete忘加where条件)

在数据库日常维护中,开发人员是最让人头痛的,很多时候都会由于SQL语句写的有问题导致服务器出问题,导致资源耗尽.最危险的操作就是在做DML操作的时候忘加where条件,导致全表更新,这是作为运维或者DBA的我们改如何处理呢?下面我分别针对update和delete操作忘加where条件导致全表更新的处理方法. 一. update 忘加where条件误操作恢复数据(binglog格式必须是ROW) 1.创建测试用的数据表 mysql> create table t1 ( -> id int un

恢复oracle中update或delete的数据

问题描述 比如在开发人员对employee表进行一个update语句,但更新完之后,才发现更新的语句有误,需要撤销刚才的update操作.如(update employee e set e.block='0300100011000000248' wheree.block='0300100011000000240'; 更新了10条数据) 1.如果在很短的时间内,可以查询数据库中的versions,记录短时间内的employee表中的update.delete.insert的操作.(时间多长取决于数

mysqlbinlog结合sed命令恢复update时未加where条件之前的数据

一.环境说明 腾讯云机器上自建MySQL 上update操作时,忘加where条件 ,使用mysqlbinlog搭配sed命令完美还原MySQL版本号:5.6.39:mysql必须开启binlog,并且mysql的binlog最好是Row模式;mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,否则在mysqlbinlog 解析出来的sql文件对于中文汉字的会出现乱码,导致最后恢复数据到线上的表中报错.满足以上条件这样可以极大的保证数据恢复的几率.当然把控好数据库的权限问题,禁止

MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解

本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍,需要的朋友参考下 MySQL数据库insert和update语句引:用于操作数据库的SQL一般分为两种,一种是查询语句,也就是我们所说的SELECT语句,另外一种就是更新语句,也叫做数据操作语句.言外之意,就是对数据进行修改.在标准的SQL中有3个语句,它们是INSERT.UPDATE以及DELETE. 用 于操作数据库的SQL一般分为两种,一种是查询语句,也就是我们所说的SEL

MySQL的delete误操作的快速恢复方法

1. 根据误操作时间定位binlog位置找到数据库的binlog存放位置,当前正在使用的binlog文件里面就有我们要恢复的数据.一般生产环境中的binlog文件都是几百M乃至上G的大小,我们不能逐行去找被删除的数据在什么位置,所以记住误操作的时间很重要,我们可以通过mysqlbinlog命令的--start-datetime参数快速定位数据位置.比如误操作时间为20181104151800,解析出的binlog内容: [[email protected] mysql]# mysqlbinlog

sql service ---- update和delete 误操作数据 ---- 恢复数据

原文出处:http://blog.csdn.net/dba_huangzj/article/details/8491327 问题: 经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了.人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题. 遇到这种情况,一般都是没有做备份,不然也不会来发问了.首先要冷静,否则会有更大的灾难.直到你放弃. 解决方法: 对于这类问题,主要是找回误操作之前的数据,在2008之前,有个很出名的

数据库编程3 Oracle 子查询 insert update delete 事务 回收站 字段操作 企业级项目案例

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> 数据库编程3 Oracle 子查询 insert update delete 事务 回收站 字段操作 企业级项目案例 实验所用数据表 子查询,解决一步不能求解 查询工资比scott高的员工信息: 子查询知识体系搭建: 解释3,查询部门是sales的员工信息: 方法1:子查询 [方法2]:多表: 优化考虑: 解释4[select],只能放单行子查询 解释4[from] 考题:显示员工姓名,薪水 解释

【Oracle】使用bbed恢复update的数据

使用bbed不仅仅可以找回已经delete的数据还可以恢复update的数据,当然过程要比恢复delete的数据复杂一些. 实验过程如下: [email protected]>create table bbed_test(x int,y varchar2(20)); Table created. [email protected]>insert into bbed_test values(1,'BADLY9'); 1 row created. [email protected]>inse