当前位置: 首页 > news >正文

硬核实战!mysql 错误操作整个表全部数据后如何恢复?附解决过程、思路(百万行SQL,通过binlog日志恢复)

mysql 错误操作整个表全部数据后如何恢复?(百万行SQL,通过binlog日志恢复)

事件起因

事情起因:以为某个表里的数据都是系统配置的数据,没有用户数据,一个字段需要覆盖替换为新的url链接,直接写下了update t_xxx set xxx = ‘https://xxxxxxxxx’ ,然后执行了,执行的时候IDEA还提示这是危险操作,我思考了下不危险,这个就是要全部覆盖,然后就点击了execute确认执行,于是翻车了,等我覆盖完去看效果的时候,惊奇的发现用户数据也被覆盖了,于是去看这个表里的数据,真有用户数据,但是值得高兴的是,全被覆盖了。。。。真是手贱啊,小心了一万年还是翻车了,全覆盖了跟删了没多大区别~~~~都是闯祸
既然事情已经发生,那就开始修复把~

在这里插入图片描述

找Binlog文件位置

binlog文件是mysql的更新记录,二进制形式。可以用于恢复数据。
这个文件每1个G为一个文件,满 了就新建一个,所以mysql运行久了这个binlog文件很多个,每个1G,建议跟我一样设置滚动删除,我是最多保留最近8个。(实验机器配置低~)

我的是mysql 8,ubuntu,我的binlog文件在这个目录

/var/lib/mysql

在这里插入图片描述

聪明的你一眼就能看出这个binlog 27号文件只有六百多兆,序号也是最新的,证明这个是最近的一个文件,就是他了,冲

读取指定时间范围内的数据操作DML

我直接查看了我这冤种操作的时间,发现大概是7分的时候操作的覆盖调数据,于是我把那一分钟里的SQL导出来(自行评估时间范围),导出为一个SQL文件
备注:mysqlbinlog工具是mysql自带的

mysqlbinlog --base64-output=DECODE-ROWS --verbose --start-datetime="2023-12-23 01:00:00" --stop-datetime="2023-12-23 01:10:00" /var/lib/mysql/binlog.000027 > restore.sql

把导出的SQL清理数据

导出的sql,我用IDEA打开的,随便你用哪个好用的文本处理工具,我们直接搜索set这个词,就能找到SQL的最开始位置如图


例如一条

### UPDATE `xx`.`t_xx`
### WHERE
###   @1=1
###   @2='xx'
###   @3=NULL
###   @4='默认'
###   @5='xx'
###   @6='xxxx'
###   @7='1'
###   @8=1
###   @9='2023-08-19 15:29:58'
###   @10='2023-08-19 18:41:06'
### SET
###   @1=1
###   @2='xx'
###   @3='xx'
###   @4='默认'
###   @5='xx'
###   @6='xx'
###   @7='1'
###   @8=1
###   @9='2023-08-19 15:29:58'
###   @10='2023-12-23 01:07:09'

这个数据的格式不难看出,记录了变更之前和之后的每个字段数据,xx为示意作用,在真实场景中就是你的真实数据,字段根据顺序@1一直到@10,证明我有10个字段,然后没个字段的值都记录了,整个结构为

update  表 
where 
每个字段的旧值
set 
每个字段的新值

那么我们现在开始处理数据
IDEA 对于这个26MB的文件直接变仅读模式,不给我编辑,于是打开了subline text这个工具处理文本

处理数据

删除update语句以外的所有无关行

找到这句错SQL的所有update语句,其它无关行全部删除

我们要的核心就是这个update语句,我们先掐头去尾,保留中间的update,我这个文件目前有100万行~
现在我这个文件只有那一个失误SQL执行的所有update语句,总共92万行~

去掉开头的###

直接搜索把###空格,这四个字符,直接替换为空字符,于是电脑卡了一会,,,电脑这会汗流浃背,风扇狂扇,过了会好像没响应,算了撸代码解决

/*** author: humorchen* date: 2023/12/23/023 1:57* desc:**/
public class RestoreData {/*** 移除头部标识** @throws Exception*/public static void removeHeadSignal() throws Exception {String file = "C:\\Users\\Administrator\\Desktop\\restore.sql";String newFile = "C:\\Users\\Administrator\\Desktop\\restore_1.sql";BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFile));BufferedReader bufferedReader = new BufferedReader(new FileReader(file));String line = null;while ((line = bufferedReader.readLine()) != null) {if (line.startsWith("### ")) {line = line.substring(4);}bufferedWriter.write(line);bufferedWriter.write("\n");}bufferedWriter.flush();bufferedWriter.close();bufferedReader.close();}public static void main(String[] args) throws Exception {removeHeadSignal();}
}

在这里插入图片描述

set和where互换

这个互换简直不要太简单,轻松的很

    /*** where和set互换** @throws Exception*/public static void reverseWhereAndSet() throws Exception {String file = "C:\\Users\\Administrator\\Desktop\\restore_1.sql";String newFile = "C:\\Users\\Administrator\\Desktop\\restore_2.sql";final String SET = "SET";final String WHERE = "WHERE";BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFile));BufferedReader bufferedReader = new BufferedReader(new FileReader(file));String line = null;while ((line = bufferedReader.readLine()) != null) {if (line.startsWith(WHERE)) {line = SET;} else if (line.startsWith(SET)) {line = WHERE;}bufferedWriter.write(line);bufferedWriter.write("\n");}bufferedWriter.flush();bufferedWriter.close();bufferedReader.close();}public static void main(String[] args) throws Exception {
//        removeHeadSignal();reverseWhereAndSet();}

在这里插入图片描述

字段替换

把字段数组作为参数数组传入函数,然后读取@多少,替换为对应下表的字段名

/*** 替换字段名** @param columnNames*/public static void replaceColumns(String[] columnNames) throws Exception {String file = "C:\\Users\\Administrator\\Desktop\\restore_2.sql";String newFile = "C:\\Users\\Administrator\\Desktop\\restore_3.sql";BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFile));BufferedReader bufferedReader = new BufferedReader(new FileReader(file));String line = null;final String PREFIX = "  @";final int PREFIX_LEN = PREFIX.length();while ((line = bufferedReader.readLine()) != null) {// line:  @1=1if (line.length() > PREFIX_LEN && line.startsWith(PREFIX)) {// 等于号位置int eqIndex = line.indexOf("=");String indexStr = line.substring(PREFIX_LEN, eqIndex);if (StrUtil.isNumeric(indexStr)) {int index = Integer.parseInt(indexStr) - 1;if (index >= 0 && index < columnNames.length) {// 替换字段名line = line.replace(PREFIX + indexStr, columnNames[index]);}}}bufferedWriter.write(line);bufferedWriter.write("\n");}bufferedWriter.flush();bufferedWriter.close();bufferedReader.close();}public static void main(String[] args) throws Exception {
//        removeHeadSignal();
//        reverseWhereAndSet();replaceColumns(new String[]{"id", "title", "icon", "type", "email", "prompt", "temperature", "keep_context", "create_time", "update_time"});}

在这里插入图片描述

加,和and

看到最后你就发现只缺标点符号,;了,那就加上,起初想去判断代码处于update、set、where三个区域里加不同的,又想到要判定最后一个不能加标点,要加空格,最后一个又是分号; 真麻烦!直接搞个后缀数组算了,反正我这个表结构是固定的于是用以下代码加上标点符号和换行。

/*** 添加,和and和;** @throws Exception*/public static void addPrefix(String[] addPrefix) throws Exception {String file = "C:\\Users\\Administrator\\Desktop\\restore_3.sql";String newFile = "C:\\Users\\Administrator\\Desktop\\restore_4.sql";BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFile));BufferedReader bufferedReader = new BufferedReader(new FileReader(file));String line = null;int index = -1;final String UPDATE = "UPDATE";while ((line = bufferedReader.readLine()) != null) {if (line.startsWith(UPDATE)) {index = 0;bufferedWriter.write("\n\n");;}if (index >= 0) {line = line + addPrefix[index];index++;}bufferedWriter.write(line);bufferedWriter.write("\n");}bufferedWriter.flush();bufferedWriter.close();bufferedReader.close();}public static void main(String[] args) throws Exception {
//        removeHeadSignal();
//        reverseWhereAndSet();
//        replaceColumns(new String[]{"id", "title", "icon", "type", "email", "prompt", "temperature", "keep_context", "create_time", "update_time"});addPrefix(new String[]{" ", " ", ",", ",", ",", ",", ",", ",", ",", ",", ",", " ", " ", " and ", " and ", " and ", " and ", " and ", " and ", " and ", " and ", " and ", " ;"});}

在这里插入图片描述

大功告成,拿去执行即可!

执行之前你先随机取个三条执行一下看看,确认自己的SQL生产对了。
我把sql上传到了ubuntu,进入mysql -uroot -p,然后use xxx;source xxx.sql;执行完数据恢复了,会有点久,如果数据量大,执行会更久。珍惜数据。。。
我这个一百万行的恢复数据SQL大约执行了3、5分钟执行完了。数据全部恢复到错误SQL前的数据了。

相关文章:

硬核实战!mysql 错误操作整个表全部数据后如何恢复?附解决过程、思路(百万行SQL,通过binlog日志恢复)

mysql 错误操作整个表全部数据后如何恢复&#xff1f;&#xff08;百万行SQL&#xff0c;通过binlog日志恢复&#xff09; 事件起因 事情起因&#xff1a;以为某个表里的数据都是系统配置的数据&#xff0c;没有用户数据&#xff0c;一个字段需要覆盖替换为新的url链接&#x…...

【什么是反射机制?为什么反射慢?】

✅ 什么是反射机制&#xff1f;为什么反射慢&#xff1f; ✅典型解析✅拓展知识仓✅反射常见的应用场景✅反射和Class的关系 ✅典型解析 反射机制指的是程序在运行时能够获取自身的信息。在iava中&#xff0c;只要给定类的名字&#xff0c;那么就可以通过反射机制来获得类的所有…...

PostGreSQL:货币类型

货币类型&#xff1a;money money类型存储固定小数精度的货币数字&#xff0c;小数的精度由数据库的lc_monetary设置决定。windows系统下&#xff0c;该配置项位于/data/postgresql.conf文件中&#xff0c;默认配置如下&#xff0c; lc_monetary Chinese (Simplified)_Chi…...

ESP8266网络相框采用TFT_eSPI库TJpg_Decoder库mixly库UDP库实现图片传送

用ESP8266和TFT_ESPI模块来显示图片数据。具体来说&#xff0c;我们将使用ILI9431显示器作为显示设备&#xff0c;并通过UDP协议将图片数据从发送端传输到ESP8266。最后&#xff0c;我们将解析这些数据并在TFT屏幕上显示出来。在这个过程中&#xff0c;我们将面临一些编程挑战&…...

Go 泛型发展史与基本介绍

Go 泛型发展史与基本介绍 Go 1.18版本增加了对泛型的支持&#xff0c;泛型也是自 Go 语言开源以来所做的最大改变。 文章目录 Go 泛型发展史与基本介绍一、为什么要加入泛型&#xff1f;二、什么是泛型三、泛型的来源四、为什么需要泛型五、Go 泛型设计的简史六、泛型语法6.1 …...

python 解决手机拍的书籍图片发灰的问题

老师给发的作业经常是手机拍的&#xff0c;而不是扫描&#xff0c;背景发灰&#xff0c;如果二次打印就没有看了&#xff0c;象这样&#xff1a; 如果使用photoshop 处理&#xff0c;有些地方还是扣不干净&#xff0c;不如python 做的好&#xff0c;处理后如下&#xff1a; 具体…...

【prompt一】Domain Adaptation via Prompt Learning

1.Motivation 当前的UDA方法通过对齐源和目标特征空间来学习域不变特征。这种对齐是由诸如统计差异最小化或对抗性训练等约束施加的。然而&#xff0c;这些约束可能导致语义特征结构的扭曲和类可辨别性的丧失。 在本文中&#xff0c;引入了一种新的UDA提示学习范式&#xff0…...

视频编辑与制作,添加视频封面的软件

如今&#xff0c;视频已经成为了我们生活中不可或缺的一部分&#xff0c;无论是社交媒体上的短视频&#xff0c;还是电影、电视剧&#xff0c;视频都以其独特的魅力吸引着我们的目光。而在这背后&#xff0c;视频剪辑软件功不可没。今天&#xff0c;我就为大家揭秘一款新一代的…...

Deepin更换仿Mac主题

上一篇博客说了要写一篇deepin系统的美化教程 先看效果图&#xff1a; 准备工作&#xff1a; 1.你自己 嘻嘻嘻 2.能上网的deepin15.11电脑 首先去下载主题 本次需要系统美化3部分&#xff1a;1.图标 2.光标 3.壁纸 开始之前&#xff0c;请先把你的窗口特效打开&#xff0c;…...

【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse

【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse 1&#xff09;导入相关依赖2&#xff09;代码实现2.1.resources2.1.1.appconfig.yml2.1.2.log4j.properties2.1.3.log4j2.xml2.1.4.flink_backup_local.yml 2.2.utils2.2.1.DBConn2.2.2.CommonUtils2.…...

浅谈Redis分布式锁(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 自定义Redis分布式锁的…...

Django Rest Framework框架的安装

Django Rest Framework框架的安装 Django Rest Framework框架的安装 1.DRF简介2.安装依赖3.安装使用pip安装添加rest_framework应用 1.DRF简介 Django REST Framework是Web api的工具包。它是在Django框架基础之上&#xff0c;进行了二次开发。 2.安装依赖 链接python安装 …...

深度学习(七):bert理解之输入形式

传统的预训练方法存在一些问题&#xff0c;如单向语言模型的局限性和无法处理双向上下文的限制。为了解决这些问题&#xff0c;一种新的预训练方法随即被提出&#xff0c;即BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;。通过在大规模…...

如何用Excel制作一张能在网上浏览的动态数据报表

前言 如今各类BI产品大行其道&#xff0c;“数据可视化”成为一个热门词汇。相比价格高昂的各种BI软件&#xff0c;用Excel来制作动态报表就更加经济便捷。今天小编就将为大家介绍一下如何使用葡萄城公司的纯前端表格控件——SpreadJS来实现一个Excel动态报表&#xff1a; 实…...

双向数据绑定是什么

一、什么是双向绑定 我们先从单向绑定切入单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新双向绑定就很容易联想到了&#xff0c;在单向绑定的基础上&#xff0c;用户更新了View&#xff0c;Mo…...

鱼眼标定方式

鱼眼作用 人单眼水平视角最大可达156度&#xff0c;垂直方向150度。为了增加可视范围&#xff0c;摄像头可以通过畸变参数扩大视野&#xff0c;一般100度到200度的fov。所以鱼眼是为了看的视野更大&#xff0c;注意在一定分辨率下&#xff0c;fov边缘的像素点稀疏&#xff0c;…...

详解Keras3.0 KerasNLP Models: GPT2 GPT2Tokenizer

1、GPT2Tokenizer 用于将文本数据转换为适合训练和预测的格式&#xff0c;主要功能是将输入的文本进行分词、编码等操作&#xff0c;以便在神经网络中使用 keras_nlp.models.GPT2Tokenizer(vocabulary, merges, **kwargs) 参数说明 vocabulary&#xff1a;一个字典&#x…...

2016年第五届数学建模国际赛小美赛B题直达地铁线路解题全过程文档及程序

2016年第五届数学建模国际赛小美赛 B题 直达地铁线路 原题再现&#xff1a; 在目前的大都市地铁网络中&#xff0c;在两个相距遥远的车站之间运送乘客通常需要很长时间。我们可以建议在两个长途车站之间设置直达班车&#xff0c;以节省长途乘客的时间。   第一部分&#xf…...

三秦通ETC续航改造

前些天开车时ETC每隔2分钟滴滴响一下&#xff0c;重插卡提示电池电压低 2.8V。看来应该是电池不行了。去银行更换ETC应该是需要费用的。还有一种办法是注销掉&#xff0c;然后去别的银行办一个。不过我想自己更换电池试一下。 首先拆下ETC&#xff0c;我使用的办法是开水烫。烧…...

使用Python实现发送Email电子邮件【第19篇—python发邮件】

文章目录 &#x1f47d;使用Python实现发送Email电子邮件&#x1f3b6;实现原理&#x1f3c3;Python实现发送Email电子邮件-基础版&#x1f46b;实现源码&#x1f646;源码解析 &#x1f487;Python实现发送Email电子邮件-完善版&#x1f46b;实现源码&#x1f646;源码解析&am…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...