mysql"闪回"技术恢复误删除误更改的数据

相信很多人都遇到过忘带where条件或者where条件漏写了一个和写错了的情况,结果执行了delete/update后把整张表的数据都给改了。传统的解决方法是:利用最近的全量备份+增量binlog备份,恢复到误操作之前的状态,但是此方法有一个弊端,那就是随着表的记录增大,binlog的增多,恢复起来会很费时费力。

现在有一个简单的方法,可以恢复到误操作之前的状态。听起来这方法似乎利用的是Oracle的闪回功能,但MySQL目前(包括最新的V5.7版本与MariaDB10.1分支版本)还不具有这样的功能,不过,我们完全可以模拟出这一功能来。使用该方法前,记得要将binlog日志设置为binlog_format = ROW,如果是STATEMENT,这个方法是无效的。切记!!

在讲解闪回恢复前,我们首先要了解一下闪回的概念。闪回就类似Windows里的回收站功能。MySQL实现闪回,是通过模拟的方式(解析binlog)来恢复数据。2012年,原淘宝彭立勋针对MySQL5.5版本,对rows格式的binlog可以进行逆向操作。delete反向生成insert,update生成反向的update。2016年,原支付宝楼方鑫针对MySQL5.6版本也同样实现了此功能。

但目前还没有针对MariaDB 10的版本,由于binlog格式与MySQL不同,无法使用此工具恢复数据,所以笔者也是通过解析binlog,用sed命令进行逆向操作,针对delete反向生成replace into,update反向生成replace into,适用于MySQL/MariaDB/Percona版本。

笔者借鉴了Percona官方博客的思路实现。https://www.percona.com/blog/2012/10/19/recovering-from-a-bad-update-statement/

注!DROP/TRUNCATE操作无法使用闪回,需要全量备份+binlog增量备份恢复。

下面笔者通过一个示例给大家演示一下。

u  误删除闪回步骤

现有一张test表,总共有10条记录,查询结果如图(1)所示。

图(1) test表数据

下面在执行delete删除操作的时候,忘加where条件,导致全表记录被删除,如图(2)所示。

图(2) test表的记录全表被删除

恢复过程

1、找到误删除的binlog保存下来

# mysqlbinlog --base64-output=decode-rows -v -v --start-datetime="2016-05-04

13:15:00" mysql-bin.000001 | grep -B 50 ‘### DELETE FROM `test`.`test`‘ | more

通过时间定位到全表删除的语句,如图(3)所示。

图(3) delete删除

此时,请注意看笔者用红色框标出的@1,@2,@3,@4,这里对应原表字段分别是id,k,c,pad,后面的=等号则对应的原表被删除的记录。

下一步,只需把这一段binlog保存下来,以待后面的恢复,执行命令如下。

# mysqlbinlog --base64-output=decode-rows -v -v mysql-bin.000001 | sed -n

‘/end_log_pos 1049/,/COMMIT/p‘ | tail -n +2 > /root/recover.binlog

查看recover.binlog,我们得到了如下内容:

# cat /root/recover.binlog

### DELETE FROM `test`.`test`

### WHERE

###   @1=1 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=2 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=3 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=4 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=5 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=6 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=7 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=8 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=9 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

### DELETE FROM `test`.`test`

### WHERE

###   @1=10 /* INT meta=0 nullable=0 is_null=0 */

###   @2=0 /* INT meta=0 nullable=0 is_null=0 */

###   @3=‘‘ /* STRING(360) meta=61032 nullable=0 is_null=0 */

###   @4=‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ /*

STRING(180) meta=65204 nullable=0 is_null=0 */

# at 1049

#160504 13:16:08 server id 17128  end_log_pos 1076      Xid = 3225

COMMIT/*!*/;

2、逆向将delete转为replace into可执行SQL语句

# cat recover.binlog | sed -n ‘/###/p‘ | sed ‘s/### //g;s/\/\*.*/,/g;s/DELETE

FROM/\nREPLACE INTO/g;s/WHERE/SELECT/g‘ | sed -r ‘s/(@4.*),/\1;/g‘ | sed

‘s/@[1-9].*=//g‘ > /root/recover.sql

注:@4代表字段的最后一位,如果你的表有10个字段,要将其改为@10

查看recover.sql,我们得到了如下内容:

# cat /root/recover.sql

REPLACE INTO `test`.`test`

SELECT

1 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

2 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

3 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

4 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

5 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

6 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

7 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

8 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

9 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

REPLACE INTO `test`.`test`

SELECT

10 ,

0 ,

‘‘ ,

‘qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt‘ ;

3、恢复

最激动人心的一幕到来了,现在就要进行最后一步的恢复操作了,把这些binlog转换成SQL语句,然后将其导入进去,执行命令如下:

# source /root/recover.sql

大功告成!你也快动手试试吧!友情提醒:千万不要在生产环境下测试哦。

u  误更改update闪回步骤

1、同理第一步

2、逆向将delete转为replace into可执行SQL语句

# cat recover.binlog | sed -n ‘/###/p‘ | sed ‘s/### //g;s/\/\*.*/,/g;‘ | sed -n ‘/UPDATE

`test`.`test`/,/SET/p‘| sed ‘s/UPDATE/REPLACE

INTO/g;s/WHERE/SELECT/g;s/SET/\n/g‘ |sed -r ‘s/(@4.*),/\1;/g‘ | sed

‘s/@[1-9].*=//g‘ > /root/recover.sql

3、同理第三步

原文地址:https://www.cnblogs.com/qinghe123/p/8134077.html

时间: 2024-11-05 20:29:03

mysql"闪回"技术恢复误删除误更改的数据的相关文章

(4.11)mysql备份还原——mysql闪回技术(基于binlog)

0.闪回技术与工具简介 mysql闪回工具比较流行三大类: [0.1]官方的mysqlbinlog:支持数据库在线/离线,用脚本处理binlog的输出,转化成对应SQL再执行.通用性不好,对正则.sed等需要较高熟练度. [0.2]第三方的mysqlbinlog工具,比官方的工具多了一个闪回功能 -B [0.3]开源的binlog2sql:兼容性比较好,使用难度小,使用简单,前提是mysql必须开启. 最佳实践:线上使用binlog2sql,线下用mysqlbinlog以及mysqlbinlog

己亥清爽恢复系列之数据文件4篇:DROP表后如何恢复(非闪回技术)

己亥清爽系列说明:清爽系列是作为恢复系列的基础篇,基于FS(File System)文件系统的手工还原恢复,也叫基于用户管理的还原恢复,来自于博客园AskScuti. 实验说明:你不小心Drop掉了一张表数据,且没能及时反应过来,后面才恍然大悟,想利用闪回Drop技术进行闪回操作,可发现表空间被挤占,导致回收站里改表已被清空.如何进行手工不完全还原恢复操作.注:在数据文件.控制文件.在线日志和归档日志都完整的情况下. 基于版本:Oracle 11gR2 11.2.0.4 AskScuti 概念说

Oracle 六大闪回技术,flashback

Flashback 技术是以Undo segment中的内容为基础的, 因此受限于UNDO_RETENTON参数. 要使用flashback 的特性,必须启用自动撤销管理表空间. 在Oracle 11g里又出了一个新特性:Oracle Flashback Data Archive. FDA通过将变化数据另外存储到创建的闪回归档区(Flashback Archive)中,以和undo区别开来, 这样就可以为闪回归档区单独设置存储策略,使之可以闪回到指定时间之前的旧数据而不影响undo策略. 在Or

Oracle闪回技术

1.Flashback Database 2.Flashback Drop 3.Flashback Table 4.Flashback Query 1.Flashback Database(利用闪回日志恢复) 描述:Oracle Flashback Database特性允许通过SQL语句Flashback Database语句,让数据库前滚到当前的前一个时间点或者SCN.闪回数据库可以迅速将数据库回到误操作或人为错误的前一个时间点,如ctrl+Z操作,可以不利用备份就快速的实现基于时间点的恢复.

Mysql闪回工具之binlog2sql的原理及其使用

生产上误删数据.误改数据的现象也是时常发生的现象,作为运维这时候就需要出来补锅了,最开始的做法是恢复备份,然后从中找到需要的数据再进行修复,但是这个时间太长了,对于大表少数数据的修复来讲,动作太大,成本也大. 当然还有其他的一些操作方法,我们今天有主角. MySQL 闪回工具 --   binlog2sql 用途 数据回滚 主从切换后数据不一致的修复 从 binlog 生成标准 SQL,带来的衍生功能 闪回原理简析 开始之前,先说说闪回.我们都知道 MySQL binlog 以 event 为单

Oracle的闪回技术--闪回错误的DML操作

提交DML操作后,该操作使用的还原段就可以被其它对象使用了,为了保证闪回操作时这些数据仍然被保存在还原段中,可能需要重新设置undo_retention参数,表示一个事务提交后,该事务的数据必须保存在还原段中的时间:但是这也并不能完全保证指定的时间的数据一定能够被恢复,还原表空间没有足够的时间时,仍会覆盖要求保留的磁盘空间. 查看undo_retention的当前值: SQL> show parameter undo_retention NAME TYPE VALUE -------------

Oracle 11g R2 闪回技术

为了使数据库能够从任何逻辑错误中迅速恢复,oracle推出了闪回技术.采用该技术,可以对行级和事物级的数据变化进行恢复,减少了数据恢复的时间,而且操作简单.通过SQL语句就可以实现数据的恢复,大大提高了数据库恢复的效率.闪回技术是数据库恢复技术历史上一次重大的进步,从根本上改变了数据恢复. 闪回技术包括以下各项: 闪回查询:(FLASHBACK QUERY):查询过去某个时间点或某个SCN值时表中的数据信息 闪回版本查询(FLASHBACK Version query):查询过去某个时间段或某个

MyFlash MySQL闪回工具

安装:环境要求:1.binlog格式必须为row,且binlog_row_image=full2.仅支持5.6与5.73.只能回滚DML(增.删.改) 下载地址:https://github.com/Meituan-Dianping/MyFlash 安装:unzip MyFlash-master.zipmv MyFlash-master /usr/local/MyFlash/gcc -w pkg-config --cflags --libs glib-2.0 source/binlogParse

Oracle闪回技术详解

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