实际工作中总会发生数据误删除的场景,在没有备份情况下,如何快速恢复误删数据就显得非常重要。

本文基于MySQL的binlog日志机制,当日志格式设置为“binlog_format=ROW”时,记录一步一步手动解析binlog、恢复误删数据的全过程,供大家参考使用。

一、确定删除时间段

查看数据库日志名字,查看操作事件,确认删除的具体时间,以定位删除的日志内容。

show master logs;

show binlog events in 'binlog.000067';

show binlog events in 'binlog.000067' FROM 1293303 LIMIT 0, 20;

通过类似如上的语句可确定具体的日志名字,具体的操作时间点或position

mysql> show binlog events in 'binlog.000002' FROM 2853160 LIMIT 0, 20;
+---------------+---------+----------------+-----------+-------------+--------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+---------+----------------+-----------+-------------+--------------------------------------+
| binlog.000002 | 2853160 | Query | 1 | 2853246 | BEGIN |
| binlog.000002 | 2853246 | Table_map | 1 | 2853315 | table_id: 94 (liking.wp_options) |
| binlog.000002 | 2853315 | Update_rows | 1 | 2859755 | table_id: 94 flags: STMT_END_F |
| binlog.000002 | 2859755 | Query | 1 | 2859842 | COMMIT |
| binlog.000002 | 2859842 | Anonymous_Gtid | 1 | 2859921 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000002 | 2859921 | Query | 1 | 2860007 | BEGIN |
| binlog.000002 | 2860007 | Table_map | 1 | 2860076 | table_id: 94 (liking.wp_options) |
| binlog.000002 | 2860076 | Update_rows | 1 | 2866516 | table_id: 94 flags: STMT_END_F |
| binlog.000002 | 2866516 | Query | 1 | 2866603 | COMMIT |
| binlog.000002 | 2866603 | Anonymous_Gtid | 1 | 2866682 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000002 | 2866682 | Query | 1 | 2866759 | BEGIN |
| binlog.000002 | 2866759 | Table_map | 1 | 2866828 | table_id: 94 (liking.wp_options) |
| binlog.000002 | 2866828 | Delete_rows | 1 | 2866936 | table_id: 94 flags: STMT_END_F |
| binlog.000002 | 2866936 | Query | 1 | 2867014 | COMMIT |
| binlog.000002 | 2867014 | Anonymous_Gtid | 1 | 2867093 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000002 | 2867093 | Query | 1 | 2867179 | BEGIN |
| binlog.000002 | 2867179 | Table_map | 1 | 2867247 | table_id: 95 (liking.wp_postmeta) |
| binlog.000002 | 2867247 | Update_rows | 1 | 2867347 | table_id: 95 flags: STMT_END_F |
| binlog.000002 | 2867347 | Query | 1 | 2867434 | COMMIT |
| binlog.000002 | 2867434 | Anonymous_Gtid | 1 | 2867513 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
+---------------+---------+----------------+-----------+-------------+--------------------------------------+

二、取到指定时间段的所有sql语句

mysqlbinlog --no-defaults --base64-output=decode-rows -vv --start-datetime="2022-10-27 16:54:00" --stop-datetime="2022-10-27 18:27:00" binlog.000288 > liking.sql

三、取delete语句

sed -n '/### DELETE FROM 数据脱敏.数据脱敏数据脱敏/,/COMMIT/p' liking.sql > liking-1.sql

得到类似如下结果:

head -50 liking-1.sql
### DELETE FROM `数据脱敏`.`数据脱敏数据脱敏`
### WHERE
### @1=222248 /* INT meta=0 nullable=0 is_null=0 */
### @2='数据脱敏数据脱敏' /* VARSTRING(256) meta=256 nullable=1 is_null=0 */
[此处省略第3~45个记录行]
### @46='数据脱敏' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
### @47='订单' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
### @48='数据脱敏' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */

四、只保留以###开始的行数据

sed -n '/^###/'p liking-1.sql > liking-2.sql

五、去掉开头的###字符

sed 's/### //g' liking-2.sql > liking-3.sql

得到类似如下结果:

head -50 liking-3.sql
DELETE FROM `数据脱敏`.`数据脱敏数据脱敏`
WHERE
@1=222248 /* INT meta=0 nullable=0 is_null=0 */
@2='数据脱敏数据脱敏' /* VARSTRING(256) meta=256 nullable=1 is_null=0 */
[此处省略第3个~第45个字段]
@46='数据脱敏' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
@47='订单' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
@48='数据脱敏' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */

六、以#作分隔符将以/*开始的内容用,替换

sed 's#/*.*#,#g' liking-3.sql > liking-4.sql

得到如下结果:

head -50 liking-4.sql
DELETE FROM `数据脱敏`.`数据脱敏数据脱敏`
WHERE
@1=222248 ,
@2='数据脱敏数据脱敏' ,
[此处省略第3个~第45个字段]
@46='数据脱敏' ,
@47='订单' ,
@48='数据脱敏' ,

七、浏览结果做对应处理

鉴于还有一些insert、update语句,只取出前面的delete语句:

sed -n '1,493200p' liking-4.sql > liking-5.sql

八、全文替换关键字,将delete改成insert

将'DELETE FROM'改成'INSERT INTO'

将'WHERE'改成'SELECT'

sed 's#DELETE FROM#INSERT INTO#g' liking-5.sql > liking-6.sql

sed 's#WHERE#SELECT#g' liking-6.sql > liking-7.sql

得到如下结果:

head -50 liking-7.sql
INSERT INTO `数据脱敏`.`数据脱敏数据脱敏数据脱敏`
SELECT
@1=222248 ,
@2='数据脱敏数据脱敏' ,
[此处省略第3个~第45个字段]
@46='数据脱敏' ,
@47='订单' ,
@48='数据脱敏' ,

九、匹配'@48='开头以','结尾的行,把','替换成';'

sed -r 's#(@48=.)(,)#\1;#g' liking-7.sql > liking-8.sql

-r: 是指将正则表达式中的需要转义的字符设置成不需转义

括号用来匹配连续出现的内容

.
标识匹配除换行符\n外的任何单元符

为了把','去掉,单独(,)

\1是用来取()表示符的第一个,并在后面拼接上';'

本次恢复的记录都是48个字段,最后加分号,标识SQL结束,比较容易理解。

得到类似如下结果:

INSERT INTO `数据脱敏`.`数据脱敏数据脱敏数据脱敏`
SELECT
@1=222248 ,
@2='数据脱敏数据脱敏' ,
[此处省略第3个~第45个字段]
@46='数据脱敏' ,
@47='订单' ,
@48='数据脱敏' ;

十、把'@??='替换成'',也就是去掉类似'@11='字样部分

sed -r 's#(@.=)(.)#\2#g' liking-8.sql > liking-9.sql

得到类似如下结果:

head -50 liking-9.sql
INSERT INTO `数据脱敏`.`数据脱敏数据脱敏`
SELECT
222248 ,
'CMHE-202200393' ,
'数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏' ,
4.1772e+07 ,
'\'8000062202216124' ,
[此处省略第6个~第45个字段]
'数据脱敏' ,
'订单' ,
'马蕾' ;

十一、最后拼接 commit 语句

sed -i '$a commit;' liking-9.sql

查看最后几行确认:

tail -51 liking-9.sql
INSERT INTO `数据脱敏`.`数据脱敏数据脱敏`
SELECT
251837 ,
'CMHE-202101003' ,
'数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏' ,
5.04e+08 ,
'\'8000004202200006' ,
[此处省略第6个~第45个字段]
'数据脱敏' ,
'订单' ,
'陈鹏3' ;
commit;

十二、浏览、调整个别异常格式字段

此时需大概浏览得到的文本结果,尤其关注转义符,如有必要,需及时调整。

发现尚存在类似如下字段格式

''8000004202200006'

如需去掉'

则如下操作:

sed "s#\'##g" liking-9.sql > liking-10.sql

最后确认如下:

tail -51 liking-10.sql
INSERT INTO `数据脱敏`.`数据脱敏数据脱敏`
SELECT
251837 ,
'CMHE-202101003' ,
'数据脱敏数据脱敏数据脱敏数据脱敏数据脱敏' ,
5.04e+08 ,
'8000004202200006' ,
[此处省略第6个~第45个字段]
'数据脱敏' ,
'订单' ,
'陈鹏3' ;
commit;

十三、执行恢复数据

经过审视、调整后,此时得到的结果,已经可以正常执行INSERT操作恢复数据了!

写在最后,再次强调,备份是运维第一要务,备份的重要性再怎么强调也不为过,除非你可以承受数据丢失带来的后果。

数据千万行,备份最重要;数据不备份,丢失泪两行!

参考文档:

https://blog.csdn.net/qq_37701372/article/details/115188461

MySQL误删恢复方法2的更多相关文章

  1. 二.误删除MySQL用户,恢复方法

    误删除MySQL用户导致无法进入数据库 一.方法一 1.停止数据库 [root@db02 ~]# /etc/init.d/mysqld stop 2.跳过授权表,跳过网络启动数据库 [root@db0 ...

  2. oracle数据库误删恢复方法

    一.如果只是误删部分数据或者某条数据可以通过 1.select * from 误删除的表明 as of timestamp to_Date('恢复年月日  时分秒', '恢复时间格式')       ...

  3. windows系统下系统变量path误删恢复方法

    每台计算机安装程序不同,环境变量path会有不同,若误删了环境变量path,可以如下完美解决.   Win+R 输入regedit打开注册表(开始-运行里输入regedit) 找到  HKEY_LOC ...

  4. Mysql误删表中数据与误删表的恢复方法

    由于头两天面试时被问了这样一个问题,如果某同事误删了某个表,你该怎么恢复? 当时想了一下,因为博主没有遇到过这个问题,但是也多少了解一些,所以就回答通过mysql的binlog日志进行恢复. 面试官当 ...

  5. MySQL全备+binlog恢复方法之伪装master【原创】

    利用mysql全备 +binlog server恢复方法之伪装master 单实例试验 一.试验环境 10.72.7.40 实例 mysql3306为要恢复的对象,mysql3306的全备+binlo ...

  6. MySQL密码的恢复方法

    MySQL密码的恢复方法之一 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态 ...

  7. mysql导出csv/sql/newTable/txt的方法,mysql的导入txt/sql方法...mysql备份恢复mysqlhotcopy、二进制日志binlog、直接备份文件、备份策略、灾难恢复.....................................................

    mysql备份表结构和数据 方法一. Create table new_table_nam备份到新表:MYSQL不支持: Select * Into new_table_name from old_t ...

  8. IIS误删了默认网站,恢复方法

    有时候安装好IIS后,会不小心把IIS的默认网站删除.重新去新建可能会出现一些错误例如"提示文件已存在无法执行"等奇怪的错误,下面是具体的默认网站的恢复方法 找到目录C:\wind ...

  9. MySQL 误删数据、误更新数据(update,delete忘加where条件)

    MySQL 误操作后数据恢复(update,delete忘加where条件) 关键词:mysql误删数据,mysql误更新数据 转自:https://www.cnblogs.com/gomysql/p ...

  10. 6种innodb数据字典恢复方法

    6种innodb数据字典恢复方法 https://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html frm文件重 ...

随机推荐

  1. Spring源码核心剖析

    前言 SpringAOP作为Spring最核心的能力之一,其重要性不言而喻.然后需要知道的是AOP并不只是Spring特有的功能,而是一种思想,一种通用的功能.而SpringAOP只是在AOP的基础上 ...

  2. Linux系统运维之Zookeeper集群配置

    一.简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.ZooKeeper的目标就是封装好复杂易 ...

  3. Win10激活步骤、密钥key

    统安装完毕后,首先以Win+R打开CMD命令行窗口,按下Win+X,选择命令提示符(管理员). Win10企业版 用户举例请依次输入: slmgr /ipk NPPR9-FWDCX-D2C8J-H87 ...

  4. 即构SDK12月迭代:新增多项质量回调,互动白板、云录制SDK同步更新

    即构SDK12月迭代来啦,本月LiveRoom/AudioRoom SDK新增了端到端延迟质量回调.房间会话ID信息,便于在音视频通话.直播场景中进行时延.通话质量的评测.同时还优化了硬件设备权限变更 ...

  5. Federated Learning001

    联邦学习--笔记001 2022.11.16周三 今天学习了联邦学习的开山之作---Communication-Efficient Learning of Deep Networks from Dec ...

  6. 3D降噪_运动估计块运动匹配

    运动估计 运动估计是视频去噪技术的重要组成之一,计算相邻两帧视频序列各像素的相对运动偏移量,从而得到其运动轨迹. 点 ( i , j ) (i,j) (i,j)和 ( x , y ) (x,y) (x ...

  7. 快速搭建 phpmyadmin 开发环境

    真的很喜欢 phpmyadmin 这个 PHP 程序. 虽然工作上基本都用 Navicat,但是很多东西都是习惯了,就很难改变! 比如建表,执行 SQL 语句,界面操作肯定是 phpmyadmin 更 ...

  8. 简单了解:Linux 硬盘分区管理命令 fdisk、parted、sfdisk、sgdisk

    支持分区格式 详情链接 fdisk MBR https://zhuanlan.zhihu.com/p/56273534 parted MBR.GPT https://www.cnblogs.com/m ...

  9. 01-jQuery的基本结构

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. zanePerfor中一套简单通用的Node前后端Token登录机制和github授权登录方式

    HI!,你好,我是zane,zanePerfor是一款我开发的一个前端性能监控平台,现在支持web浏览器端和微信小程序端. 我定义为一款完整,高性能,高可用的前端性能监控系统,这是未来会达到的目的,现 ...