MySQL【Delete误操作】数据恢复【转】
前言:
操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和binlog差来恢复,等不了,很费时。这里先说明下因为Delete 操作的恢复方法:主要还是通过binlog来进行恢复,前提是binlog_format必须是Row格式,否则只能通过备份来恢复数据了。
方法:
条件:开启Binlog,Format为Row。
步骤:
1.通过MySQL自带工具mysqlbinlog 指定导出操作的记录:
- mysqlbinlog --no-defaults --start-datetime='2017-03-16 14:56:00' --stop-datetime='2017-03-16 14:57:00' -vv mysql-bin. > /tmp/restore/binlog.txt
2.数据取出来之后,需要把数据解析反转,原始数据:
- ### DELETE FROM test.me_info
- ### WHERE
- ### @= /* INT meta=0 nullable=0 is_null=0 */
- ### @='1984:03:17' /* DATE meta=0 nullable=1 is_null=0 */
- ### @=NULL /* DATE meta=765 nullable=1 is_null=1 */
- ### @=-- :: /* DATETIME meta=0 nullable=0 is_null=0 */
- ### @='' /* VARSTRING(765) meta=765 nullable=1 is_null=0 */
- ### @= /* TINYINT meta=0 nullable=1 is_null=0 */
- ### @='' /* VARSTRING(765) meta=765 nullable=1 is_null=0 */
- ### @=- () /* INT meta=0 nullable=1 is_null=0 */
- ### @= /* MEDIUMINT meta=0 nullable=1 is_null=0 */
- ### @=NULL /* MEDIUMINT meta=0 nullable=1 is_null=1 */
- ### @= /* TINYINT meta=0 nullable=1 is_null=0 */
- ### @= /* TINYINT meta=0 nullable=1 is_null=0 */
- ### @='' /* VARSTRING(765) meta=765 nullable=1 is_null=0 */
- ### @='' /* VARSTRING(765) meta=765 nullable=1 is_null=0 */
- ### @= /* MEDIUMINT meta=0 nullable=1 is_null=0 */
- ### @= /* INT meta=0 nullable=1 is_null=0 */
- ……………………
- ……………………
- ……………………
Row格式的binlog记录的格式如上面所示,需要做的工作就是吧Delete的操作转换成Insert操作,发上面的都是有一定规律的,并且需要注意的是:
1、字段类型 DATETIME 日期。在日志中保存的格式为 @4=2017-03-16 00:00:00,需要将2017-03-16 00:00:00加上引号。
2、负数。在日志中保存的格式为 @1=-1 (4294967295), -2(4294967294),-3(4294967293),需要将括号里面的数据去掉,只保留@1=-1。
3、转义字符集。如:'s,\,等。
上面3点清楚之后,可以写一个脚本(水平有限,在提升中,写的不好看):
- #!/bin/env python
- # -*- encoding: utf-8 -*-
- #-------------------------------------------------------------------------------
- # Name: restore_insert.py
- # Purpose: 通过Binlog恢复Delete误操作数据
- #-------------------------------------------------------------------------------
- def read_binlog(file,column_num):
- f=open(file)
- num = '@'+str(column_num)
- while True:
- lines = f.readline()
- if lines.strip()[0:3] == '###':
- lines=lines.split(' ',3)
- if lines[1] == 'DELETE' and lines[2] =='FROM': #该部分替换Delete为Insert
- lines[1] = "INSERT"
- lines[2] = 'INTO'
- lines[-1] = lines[-1].strip()
- if lines[1].strip() == 'WHERE':
- lines[1] = 'VALUES ('
- if ''.join(lines).find('@') <> -1 and lines[3].split('=',1)[0] <> num: #num为列数,要是小于最大的列数,后面均加,
- lines[3] = lines[3].split('=',1)[-1].strip()
- if lines[3].strip('\'').strip().find('\'') <> -1:
- lines[3] = lines[3].split('/*')[0].strip('\'').strip().strip('\'').replace('\\','\\\\').replace('\'','\\\'') #这里过滤掉转义的字符串
- lines[3] = '\'' + lines[3] + '\','
- elif lines[3].find('INT meta') <> -1: #过滤Int类型的字段为负数后带的(),正数不受影响
- lines[3] = lines[3].split('/*')[0].strip()
- lines[3] = lines[3].split()[0] + ','
- elif lines[3].find('NULL') <> -1:
- lines[3] = lines[3].split('/*')[0].strip()
- lines[3] = lines[3] + ','
- else:
- lines[3] = lines[3].split('/*')[0].strip('\'').strip().strip('\'').replace('\\','\\\\').replace('\'','\\\'') #这里过滤掉转义的字符串
- lines[3] = '\'' + lines[3].strip('\''' ') + '\','
- if ''.join(lines).find('@') <> -1 and lines[3].split('=',1)[0] == num: #num为列数,要是小于最大的列数,后面均加);
- lines[3] = lines[3].split('=',1)[-1].strip()
- if lines[3].find('\'') <> -1:
- lines[3] = lines[3].split('/*')[0].strip('\'').strip().strip('\'').replace('\\','\\\\').replace('\'','\\\'') #同上
- lines[3] = '\'' + lines[3] + '\');'
- elif lines[3].find('INT meta') <> -1: #同上
- lines[3] = lines[3].split('/*')[0].strip()
- lines[3] = lines[3].split(' ')[0] + ');'
- elif lines[3].find('NULL') <> -1:
- lines[3] = lines[3].split('/*')[0].strip()
- lines[3] = lines[3] + ');'
- else:
- lines[3] = lines[3].split('/*')[0].strip('\'').strip().strip('\'').replace('\\','\\\\').replace('\'','\\\'') #同上
- lines[3] = '\'' + lines[3].strip('\''' ') + '\');'
- print ' '.join(lines[1:])
- if lines == '':
- break
- if __name__ == '__main__':
- import sys
- read_binlog(sys.argv[1],sys.argv[2])
执行脚本:方法:python 脚本名 binlog文件 字段数目
- python restore.py binlog.txt > binlog.sql
命令行中的36 表示 需要还原的表的字段有36个,效果:
- INSERT INTO test.me_info
- VALUES (
- 2123269,
- '1990:11:12',
- NULL,
- 2,
- '',
- 0,
- '',
- -1,
- 0,
- 340800,
- 1,
- 0,
- '',
- ……
- ……
- 1,
- NULL
- );
最后还原:
- mysql test < binlog.sql
MySQL【Delete误操作】数据恢复【转】的更多相关文章
- MySQL的delete误操作的快速恢复方法
1. 根据误操作时间定位binlog位置找到数据库的binlog存放位置,当前正在使用的binlog文件里面就有我们要恢复的数据.一般生产环境中的binlog文件都是几百M乃至上G的大小,我们不能逐行 ...
- 记一次生产mysql数据误操作恢复过程
提示:建议每次对数据库进行修改时都做下备份 注意:以下Mysql开启的是row格式的binlog日志,确定到误操作具体时间可能有些麻烦,默认的格式就能很快找出来.这里开启row的原因是还有一种更快的方 ...
- 数据库周刊28│开发者最喜爱的数据库是什么?阿里云脱口秀聊程序员转型;MySQL update误操作;PG流复制踩坑;PG异机归档;MySQL架构选型;Oracle技能表;Oracle文件损坏处理……
热门资讯 1.Stackoverflow 2020年度报告出炉!开发者最喜爱的数据库是什么?[摘要]2020年2月,近6.5万名开发者参与了 Stackoverflow 的 2020 年度调查,这份报 ...
- mysql 防止update/delete误操作
身为一php开发攻城狮,常常涉及在应用中写update/delete语句,忘记加where,后果不堪设想. 还会出现在cml下直接操作mysql的情况,如果mysql 权限够大,一个update/de ...
- sql server Delete误操作后如何恢复数据
声明:本文是根据别人的经验https://blog.csdn.net/dba_huangzj/article/details/8491327写的总结 说明:update和delete时没有加where ...
- Oracle误操作 数据恢复
SELECT * FROM v$sqlarea //查询最近sql记录 SELECT r.FIRST_LOAD_TIME,r.* FROM v$sqlarea r ORDER BY r.FIRST_L ...
- MySQL【Update误操作】回滚(转)
前言: 继上一篇MySQL[Delete误操作]回滚之后,现在介绍下Update回滚,操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和bi ...
- MySQL 误操作后数据恢复(update,delete忘加where条件)【转】
在数据库日常维护中,开发人员是最让人头痛的,很多时候都会由于SQL语句 写的有问题导致服务器出问题,导致资源耗尽.最危险的操作就是在做DML操作的时候忘加where条件,导致全表更新,这是作为运维或者 ...
- MySQL 误操作后数据恢复(update,delete忘加where条件)
在数据库日常维护中,开发人员是最让人头痛的,很多时候都会由于SQL语句写的有问题导致服务器出问题,导致资源耗尽.最危险的操作就是在做DML操作的时候忘加where条件,导致全表更新,这是作为运维或者D ...
随机推荐
- kibana从入门到精通-Kibana安装
作者其他ELK快速入门系列文章 Elasticsearch从入门到精通 logstash快速入门实战指南 简介 Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之 ...
- shell脚本--cut命令
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 1.1 选项说明 cut命令将行按指定的分隔符分割成多列,它的 ...
- SpringBoot之打成war包部署到Tomcat
正常情况下SpringBoot项目是以jar包的形式,正常情况下SpringBoot项目是以jar包的形式,并且SpringBoot是内嵌Tomcat服务器,所以每次重新启动都是用的新的Tomcat服 ...
- shell编程基础(四): shell脚本语法之函数及调试
一.Shell脚本中的函数 和C语言类似,Shell中也有函数的概念,但是函数定义中没有返回值也没有参数列表.例如: #! /bin/sh fun(){ echo "Function fun ...
- 反爬虫——使用chrome headless时一些需要注意的细节
以前我们介绍过chrome headless的用法(https://www.cnblogs.com/apocelipes/p/9264673.html). 今天我们要稍微提一下其中一个细节. 反爬和w ...
- OpenCV神技——人脸检测,猫脸检测
简介 OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 ...
- mvc 中合并两个list集合
有时候,在进行查询操作的时候需要将从数据库中查询的两张表进行合并,成为一张表然后返回给前端.或者在原有的一张表基础上面加几个新的字段. 这个时候可以新建一个.class[model类],在这个新建的m ...
- 从零开始学安全(九)●OSI参考模型分层
主要分为7层和网络7层模型一样 物理层主要传输数据比特流 可以理解信号 数据链路层 逻辑层 像是交换机 网络层 又交换机发送到路由器 应用层 应用通信
- [日常] HTTP的缓存
web缓存: 1.可以自动保存常见文档副本的HTTP设备,当web请求抵达缓存时,如果存在缓存副本,就直接从本地存储设备返回,而不是去源服务器获取 2.缓存命中和未命中 3.HTTP再验证,检测服务器 ...
- [angularjs] angularjs系列笔记(四)过滤器
过滤器可以使用一个管道字符(|)添加到表达式和指令中,这不就是模板函数吗 <body> <div ng-app="Home"> <div ng-con ...