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

本文基于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. CPU性能指标介绍及分析

    CPU是计算机系统中最核心的组件之一,对系统性能起着至关重要的作用.以下是一些常见的CPU性能指标及其分析: 1. %user(用户态)和 %system(内核态) %user:表示CPU花费在用户进 ...

  2. CocosCreator + Vscode + Ts 代码注释生成文档,利用typedoc

    需求: 脚本的代码注释,生成为文档 基本搭建环境: (cocoscreator 2.4.x + vscode + ts) .(nodejs + npm) 步骤: 1.安装typedoc: npm in ...

  3. 【技术积累】HTML+CSS+JavaScript中的基础知识【一】

    HTML基础标签 <html> 定义HTML文档的根元素. <!DOCTYPE html> <html> <head> <title>My ...

  4. Linux 压缩文件用法

    # tar 命令:可以用来压缩或解压缩文件: # 压缩 tar -czvf filename.tar.gz files # 解压缩 tar -xzvf filename.tar.gz # gzip 命 ...

  5. linux 软件包:UnixBench 性能测试工具、跑分神器

    目录 安装 使用 结果示例 测试项说明 UnixBench是一个类unix系(Unix,BSD,Linux)统下的性能测试工具,一个开源工具,被广泛用与测试linux系统主机的性能.Unixbench ...

  6. 2022-1-11 控件学习3 文本渲染、TabIndex、Border、Slider、ProgressBar、

    WPF文本渲染  TextOptions.TextFormattingMode:默认值Ideal大部分是好用的,但是非常小的文本使用Display渲染会好一些 TextRenderMode:使用抗锯齿 ...

  7. Robot Framework 自动化测试随笔(一)

    一.安装Robot Framework步骤(安装目录避免中文和特殊字符,建议以管理员身份进行全部安装过程): 1.查看ride最新支持的python版本,据此下载对应python版本: https:/ ...

  8. Git SSH 认证配置

    [前言] 我们在开发过程中,经常会和github,gitlab或者gitee打交道,一般临时克隆(clone)其他人的项目学习参考时,我们大多采用 https 的方式进行 clone 但如果在参与多个 ...

  9. 【overcome error】dereferencing pointer to incomplete type

    @ 目录 前言 解决 代码情况 分析问题 尾声 前言 这个问题是我在学习数据结构链栈部分遇到的,英文报错如题所示,中文意思是:取消引用不完整类型的指针,在百度一圈也没明白,(百度搜索,看一个和全看基本 ...

  10. TypeScript: 類型 'HTMLElement | null' 不可指派給類型 'HTMLElement'。 類型 'null' 不可指派給類型 'HTMLElement'

    报错截图 解决方案 在结尾添加叹号 // 获取页面中food的元素并将其赋值给element this.element = document.getElementById('food')!;