前提条件
首先保证开启了binlog二进制日志,在MySQL配置文件my.cnf中查看是否开启
log_bin=mysql-bin
找到日志文件
日志文件一般放在MySQL的data目录下,文件名类似mysql-bin.000001这种的就是,通过文件修改时间找到最新的那个日志文件
使用mysqlbinlog命令导出数据
1、把找到的日志文件复制到MySQL的bin目录下,一来拷贝一份以防万一,再一个方便后续命令中定位文件路径
2、在bin目录运行cmd,输入命令导出数据
mysqlbinlog --no-defaults --base64-output=decode-rows -vv --start-datetime="2024-12-02 16:40:00" --stop-datetime="2024-12-02 16:55:00" --database=your_database_name mysql-bin.000014 > truncate_recovery.sql
网上有些帖子这个命令中不带–base64-output=decode-rows这个参数,这会导致导出的数据还是二进制格式,没法查看。所以这个参数必须加上。
其他几个参数也好理解,开始时间和结束时间就是需要误删的那个时间点,时间范围可以稍微拉长一点。
–database=your_database_name 这里注意替换成你的数据库名字,注意不是连接名,是database的名字。
最后输出内容到truncate_recovery.sql这个文件中。
解析日志内容
清空表和删除数据,都可以在导出的文件中搜关键字DELETE
删除的数据都会在下面详细的列出来。
到这一步网上的帖子就会建议你用反写的工具去生成insert语句了,感兴趣可以搜一下myFlash工具。
咱作为Java开发看到这种文字处理还需要麻烦别人吗,直接手写一个函数就搞定了。
1、首先把数据相关的内容拷出来,单独放一个文件。
2、写一个main方法,io流读取文件内容,String Api处理文字内容,再将处理的内容写到另一个文件中。目的就是拼接成一个insert语句,代码如下:
public static void main(String[] args) {
String filePath = "C:\\Users\\DogEgg\\Desktop\\revert.txt"; // 替换为你的文件路径
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
// 把内容写到该文件中,我这里图省事没指定路径,后续用everything搜一下文件名就行。
FileWriter writer = new FileWriter("example2.txt");
// io流逐行读取文件内容
while ((line = br.readLine()) != null) {
if (line.contains("@")) {
if (line.contains("@1=")) {
writer.write("(");
}
if (line.contains("2024-")) {
writer.write("STR_TO_DATE(");
}
writer.write(line.substring(line.indexOf("=") + 1, line.indexOf("*") - 2));
if (line.contains("2024-")) {
writer.write(", '%Y-%m-%d %H:%i:%s')");
}
if (!line.contains("@30=")) {
writer.write(",");
}
if (line.contains("@30=")) {
writer.write("),");
}
}
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
内容处理的逻辑大家自由发挥,我这里因为着急恢复数据,写的很随意。
需要注意的就是日期格式要做转换,我这里用了STR_TO_DATE方法去转换格式,否则会报错类型不匹配。
找到输出的文件,打开看到内容就很眼熟了,都是(xx,xx,xx),(xx,xx,xx)这种格式的,只需要前面拼接insert into table_name(字段名1,字段名2…) values就够了,然后直接执行该sql文件。
完美结束。