【后端记录】修复MySql的错误修改的数据记录【binlog修复】

前言

今天入门后端的时候,不小心改了非预期的数据,因为还没学到事务,所以恢复数据还比较麻烦,站在巨人的肩膀上还是解决了,原文连接在下面

https://blog.csdn.net/qq_42874315/article/details/140480570

解决办法

原理就是找到错误的sql语句记录,根据sql语句生成脚本,把sql语句“回滚”回之前数据。
步骤如下:

  1. MySql默认是开启binlog的,查询指令是
    show variables like 'log_bin';
    在这里插入图片描述

  2. 查看binlog文件在本地的路径

SHOW VARIABLES LIKE 'log_bin_index'; //C:\ProgramData\MySQL\MySQL Server 8.0\Data\MYSZ-TIANW-bin

我们定位到自己的Data对应的文件夹
在这里插入图片描述
这个对应着修改的时间,我们找到对应时间修改的文件,我这里是bin.000010

  1. 需要知道你修改的大致的时间,执行cmd命令

需要cd到对应目录 :
cd C:\ProgramData\MySQL\MySQL Server 8.0\Data

mysqlbinlog --no-defaults --start-datetime="2024-08-15 14:00:00" --stop-datetime="2024-08-15 14:50:28" --base64-output=DECODE-ROWS --verbose bin.000010 

命令有三个参数要改,开始和结束时间,日志的名称。开始结束时间如果不知道的话范围由大到小,慢慢缩减,注意名称bin.000010需要文件夹中的全称 需要结合你自己日志的名称。

假设我的错误的sql语句是(demo数据库)

update t_emp set job  = "ANALYST",deptno = 20;

则部分的输出结果如下:
在这里插入图片描述
其中@3是job列,@8是deptno,修改的时间是14:09:04

如果觉得cmd面板不好分析 也可以转成txt查看执行:mysqlbinlog bin.000010 > ./binlog.txt

  1. 定位到是14:09:04时间后就可以保存对应的日志出来,生成对应的文件(其实就是截取文本而已)
mysqlbinlog --no-defaults --start-datetime="2024-08-15 14:09:00" --stop-datetime="2024-08-15 14:10:00" --base64-output=DECODE-ROWS --verbose bin.000010 > error_binlog_2024-08-15-14-09.sql
  1. 用idea执行下面代码,生成对应的sql语句(就是字符替换,修改改成你表中对应的字段)
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MySqlCallbackData {
    public static void main(String[] args) {
        String filePath = "C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Data\\error_binlog_2024-08-15-14-09.sql";

        String document = readFileContent(filePath);
        List<String> updateStatements = parseDocument(document);
        for (String statement : updateStatements) {
            System.out.println(statement);
        }
    }

    /**
     * 读取文本内容
     */
    private static String readFileContent(String filePath) {
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader(new File(filePath)))) {
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    /**
     * 解析文本内容
     */
    private static List<String> parseDocument(String document) {
        List<String> updateStatements = new ArrayList<>();

        // 每个"### UPDATE "是一条更新语句
        String[] sections = document.split("### UPDATE ");
        for (int i = 1; i < sections.length; i++) {
            String section = sections[i];
            String[] lines = section.split("\n");

            // 待拼接的WHERE条件
            String whereClause = "";
            // 待拼接的SET
            StringBuilder sb = new StringBuilder();

            for (String line : lines) {
                if (line.startsWith("###   @1=")) {
                    whereClause = "empno = " + line.split("=")[1];
                } else if (line.startsWith("###   @3=")) {
                    //需要改成你表中的字段
                    sb.append("job = " + line.split("=")[1]);
                } else if (line.startsWith("###   @8=")) {
                    //需要改成你表中的字段
                    sb.append(",deptno = " + line.split("=")[1]);
                }

                // 不需要读取日志文件中SET的内容,跳过即可
                if (line.startsWith("### SET")) {
                    break;
                }
            }

            // 拼接SQL 需要改成你的表名字
            String updateStatement = "UPDATE t_emp " + "SET " + sb + " WHERE " + whereClause + ";";

            updateStatements.add(updateStatement);
        }

        return updateStatements;
    }
}

编译器输出如下,拿到sql语句数据库执行下就恢复了:

UPDATE t_emp SET job = 'CLERK',deptno = 20 WHERE empno = 7369;
UPDATE t_emp SET job = 'SALESMAN',deptno = 30 WHERE empno = 7370;
UPDATE t_emp SET job = 'SALESMAN',deptno = 30 WHERE empno = 7521;
UPDATE t_emp SET job = 'MANAGER',deptno = 20 WHERE empno = 7566;
UPDATE t_emp SET job = 'SALESMAN',deptno = 30 WHERE empno = 7654;
UPDATE t_emp SET job = 'MANAGER',deptno = 30 WHERE empno = 7698;
UPDATE t_emp SET job = 'MANAGER',deptno = 10 WHERE empno = 7782;
UPDATE t_emp SET job = 'PRESIDENT',deptno = 10 WHERE empno = 7839;
UPDATE t_emp SET job = 'SALESMAN',deptno = 30 WHERE empno = 7844;
UPDATE t_emp SET job = 'CLERK',deptno = 20 WHERE empno = 7876;
UPDATE t_emp SET job = 'CLERK',deptno = 30 WHERE empno = 7900;
UPDATE t_emp SET job = 'CLERK',deptno = 10 WHERE empno = 7934;
UPDATE t_emp SET job = 'CLERK',deptno = NULL WHERE empno = 7999;

总结

sql语句修改数据需要很谨慎才行,后台之路任重而道远啊~

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值