AI 提示词
[root@appdb-01 qding]# ls
mysqld-bin.054733 mysqld-bin.054736 mysqld-bin.054739 mysqld-bin.054742 mysqld-bin.054745 relay.000101 relay.000104 relay.index
mysqld-bin.054734 mysqld-bin.054737 mysqld-bin.054740 mysqld-bin.054743 mysqld-bin.index relay.000102 relay.000105
mysqld-bin.054735 mysqld-bin.054738 mysqld-bin.054741 mysqld-bin.054744 relay.000100 relay.000103 relay.000106
[root@appdb-01 qding]#
这是我的binlog文件, 我刚刚执行的delete语句误删除了部分数据,我想恢复我删除的数据。涉及的数据库是db_iam 数据表是 t_iam_func_auth
进入binlog目录

确认最新binlog文件
根据文件列表,最新的是mysqld-bin.054745(数字最大的文件)6。
解析binlog内容
使用mysqlbinlog工具解析,注意添加--database
和--base64-output
参数:
shell
mysqlbinlog --base64-output=decode-rows -v --database=db_iam mysqld-bin.054745 > parsed_binlog.sql
定位DELETE语句
在生成的parsed_binlog.sql中搜索以下内容:
表名t_iam_func_auth
操作类型### DELETE FROM,这是其中部分数据:
### @17='XZ'
### @18='增加问卷配置人员权限'
### @19=NULL
# at 154852463
#250610 16:50:29 server id 453309 end_log_pos 154852494 CRC32 0x70183b1f Xid = 635330624
COMMIT/*!*/;
# at 154852494
#250610 16:50:29 server id 453309 end_log_pos 154852559 CRC32 0x36be420c Anonymous_GTID last_committed=5320 sequence_number=16105 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 154852559
#250610 16:50:29 server id 453309 end_log_pos 154852635 CRC32 0xfd531c3d Query thread_id=6117380 exec_time=0 error_code=0
SET TIMESTAMP=1749545429/*!*/;
BEGIN
/*!*/;
# at 154852635
# at 154852753
#250610 16:50:29 server id 453309 end_log_pos 154852866 CRC32 0xe6a38df5 Table_map: `db_iam`.`t_iam_func_auth` mapped to number 56488
# at 154852866
#250610 16:50:29 server id 453309 end_log_pos 154853264 CRC32 0x448e2624 Delete_rows: table id 56488 flags: STMT_END_F
### DELETE FROM `db_iam`.`t_iam_func_auth`
### WHERE
### @1='00c5383a-d564-47e8-b905-7335e740ea31'
### @2='FP.XZ.QUESTION.7858636'
### @3='9ea88e7d-b92e-4c8b-a394-cb7fc6b93d9b'
### @4='edd8239e-a049-4bdc-954f-41fa60c6894c'
### @5='U'
### @6=1
### @7=0
### @8='605aeca6-01a8-4172-959f-34fff0cf0e67'
### @9=1742459189
### @10='605aeca6-01a8-4172-959f-34fff0cf0e67'
### @11=1743040916
### @12='984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5'
### @13='88c514fd-7c1f-4696-8a2c-cfa49ae1e2c2'
### @14=NULL
### @15=NULL
### @16='984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5'
### @17='XZ'
### @18='系统初始化'
### @19=NULL
# at 154853264
#250610 16:50:29 server id 453309 end_log_pos 154853295 CRC32 0x5bd6c7f8 Xid = 635330630
COMMIT/*!*/;
# at 154853295
#250610 16:50:29 server id 453309 end_log_pos 154853360 CRC32 0x3354fd33 Anonymous_GTID last_committed=5320 sequence_number=16106 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 154853360
#250610 16:50:29 server id 453309 end_log_pos 154853436 CRC32 0x64d6f71e Query thread_id=6117380 exec_time=0 error_code=0
SET TIMESTAMP=1749545429/*!*/;
BEGIN
/*!*/;
# at 154853436
# at 154853554
#250610 16:50:29 server id 453309 end_log_pos 154853667 CRC32 0x1fb2c80b Table_map: `db_iam`.`t_iam_func_auth` mapped to number 56488
# at 154853667
#250610 16:50:29 server id 453309 end_log_pos 154854080 CRC32 0x2a7b4493 Delete_rows: table id 56488 flags: STMT_END_F
### DELETE FROM `db_iam`.`t_iam_func_auth`
### WHERE
### @1='027c0a0c-9c1c-4fca-ab18-4ebfdafe3ab2'
### @2='FP.XZ.QUESTION.7858778'
### @3='9cd3db3c-75a0-48bf-a047-9e30deb57c33'
### @4='edd8239e-a049-4bdc-954f-41fa60c6894c'
### @5='R'
### @6=1
### @7=0
### @8='1a7a3bb3-eeb9-454e-b458-d2da75c9539f'
### @9=1747275151
### @10='1a7a3bb3-eeb9-454e-b458-d2da75c9539f'
### @11=1747275343
### @12='984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5'
### @13='88c514fd-7c1f-4696-8a2c-cfa49ae1e2c2'
### @14=NULL
### @15=NULL
### @16='984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5'
### @17='XZ'
### @18='增加问卷配置人员权限'
### @19=NULL
# at 154854080
#250610 16:50:29 server id 453309 end_log_pos 154854111 CRC32 0x3d46f972 Xid = 635330631
COMMIT/*!*/;
# at 154854111
#250610 16:50:29 server id 453309 end_log_pos 154854176 CRC32 0xc755be74 Anonymous_GTID last_committed=5320 sequence_number=16107 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 154854176
#250610 16:50:29 server id 453309 end_log_pos 154854252 CRC32 0x103fa6aa Query thread_id=6117380 exec_time=0 error_code=0
SET TIMESTAMP=1749545429/*!*/;
BEGIN
/*!*/;
通过JAVA代码还原SQL语句
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BinlogToInsertConverter {
private static final Pattern DELETE_PATTERN = Pattern.compile(
"### DELETE FROM `([^`]+)`\\.`([^`]+)`.*?### WHERE(.*?)(?=# at|COMMIT)",
Pattern.DOTALL
);
private static final Pattern FIELD_PATTERN = Pattern.compile(
"###\\s+@(\\d+)='?(.*?)'?(?:\\s|$|NULL)",
Pattern.DOTALL
);
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
String filePath = "/Users/admin/Downloads/parsed_binlog.txt";
try {
List<String> insertStatements = convertDeleteToInsert(filePath);
for (String insert : insertStatements) {
System.out.println(insert+";");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static List<String> convertDeleteToInsert(String filePath) throws IOException {
List<String> result = new ArrayList<>();
StringBuilder fileContent = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
fileContent.append(line).append("\n");
}
}
Matcher deleteMatcher = DELETE_PATTERN.matcher(fileContent.toString());
while (deleteMatcher.find()) {
String database = deleteMatcher.group(1);
String table = deleteMatcher.group(2);
String whereClause = deleteMatcher.group(3);
List<String> values = new ArrayList<>();
Matcher fieldMatcher = FIELD_PATTERN.matcher(whereClause);
while (fieldMatcher.find()) {
String fieldNum = fieldMatcher.group(1);
String value = fieldMatcher.group(2);
if ("NULL".equals(value)) {
values.add("NULL");
} else if ("9".equals(fieldNum) || "11".equals(fieldNum)) {
// 处理时间戳字段
try {
long timestamp = Long.parseLong(value);
String formattedDate = DATE_FORMAT.format(new Date(timestamp * 1000L));
values.add("'" + formattedDate + "'");
} catch (NumberFormatException e) {
values.add("'" + value.replace("'", "''") + "'");
}
} else {
values.add("'" + value.replace("'", "''") + "'");
}
}
if (!values.isEmpty()) {
String insert = String.format(
"INSERT INTO `%s`.`%s` VALUES (%s)",
database, table, String.join(", ", values)
);
result.add(insert);
}
}
return result;
}
}
这里注意时间搓转为年月日格式。else if ("9".equals(fieldNum) || "11".equals(fieldNum))
这段代码需要修改。
最后生成类似的代码:
sql
INSERT INTO `db_iam`.`t_iam_func_auth` VALUES ('feaa322a-c7de-4c76-a07f-1d2c6d58ee37', 'FP.XZ.QUESTION.7858767', '9cd3db3c-75a0-48bf-a047-9e30deb57c33', '005f1c8a-7b9b-435d-b0cd-cc636d19f617', '9e57750d-2b2d-453b-a500-5c9e3bff2e75', '1', '0', '1a7a3bb3-eeb9-454e-b458-d2da75c9539f', '2025-05-15 10:12:31', '1a7a3bb3-eeb9-454e-b458-d2da75c9539f', '2025-05-15 10:15:34', '984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5', '88c514fd-7c1f-4696-8a2c-cfa49ae1e2c2', '', '', '984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5', 'XZ', '增加问卷配置人员权限', '');
INSERT INTO `db_iam`.`t_iam_func_auth` VALUES ('ff61bac9-ebb4-4fa7-bcda-016e7cb0d4bf', 'FP.XZ.QUESTION.7858656', '9ea88e7d-b92e-4c8b-a394-cb7fc6b93d9b', '39bbf469-c86b-4321-9f1c-2e7ac512bbcb', '043351b6-6ea1-4242-9085-7c4e7f9d9483', '1', '0', '605aeca6-01a8-4172-959f-34fff0cf0e67', '2025-03-26 11:32:18', '605aeca6-01a8-4172-959f-34fff0cf0e67', '2025-03-27 10:01:56', '984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5', '88c514fd-7c1f-4696-8a2c-cfa49ae1e2c2', '', '', '984ff0e4-68ad-4ca1-a1bf-d38d4f785ae5', 'XZ', '系统初始化', '');
最后核对数据还原数据库数据