【误更新整张数据库表某字段值的还原方法】
set为一条修改记录,where是原来的状态,set是更新的状态,@num对应字段,我的status是@13,update前有# at pos,这就可以确认区间)找到对应区间的日志,查看日志,找到更新的区间,根据 # at去定位,修改的范围,比如我等一下修改为NONPAY,第二下修改为PAID。使用mysqlbinlog查看binlog日志是否有记录你update的记录,如果有,那就是在当前bin
误更新整张数据库表某字段值的还原方法
起因
- 某个上午,写完需求后开始自测,数据库拟了些假数据,由于是重复使用该条记录多次debug,就写了条sql去修改status字段的值。
update table set status = 'PAID'; - 这操作简直下饭了,连条件都忘写了,吃完饭回来再看发现怎么看这么不对劲。咦?这里没有条件怎么知道我要更新哪条,这么智能了嘛?逐渐意识到十分有十二分不对劲。去看了一些表记录数有1万多条记录,状态全改为PAID了,再改为PAID前,还更新为NONPAY过,这就两次更新记录了。咋整啊,模型用多了sql都写不明白了。嗯,这锅还得ai模型来背。既然是模型的锅,那也得有模型来解决了,马上就给了两种方案。
方式1
-
binlog2sql。这种方式是本地数据库或者有服务器数据库的root权限才可以。
-
使用sql查看binlog日志是否开启
show variables like 'log_bin';
-
查看binlog日志文件名
show master status;
-
查看文件是否记录操作时间的相关操作(navicat的tools->history log可以看到sql操作和对应时间),找到update的时间节点

-
使用mysqlbinlog查看binlog日志是否有记录你update的记录,如果有,那就是在当前binlog日志中,没有则
SHOW BINARY LOGS;查看更多binlog日志文件,可能是倒数第二个文件。mysqlbinlog --no-defaults -h 你的ip -P 你的数据库端口 -u 账号 -p --read-from-remote-server -v --base64-output=DECODE-ROWS --start-datetime="2026-01-26 12:20:00" --stop-datetime="2026-01-26 12:30:00" binlog.000184 > rollback_1220.txt -
确定了日志文件,如果有python环境。安装binlog2sql工具
# 1. 安装工具 pip install binlog2sql- 然后使用binlog2sql根据日志文件回滚。
-
# 2. 预览回滚语句 (闪回模式)
python binlog2sql.py -h 127.0.0.1 -P 3306 -u root -p'你的密码' \
-d 你的数据库名 -t 表名 \
--start-file='binlog.000185' \
--start-datetime='2026-01-26 14:10:00' \
--stop-datetime='2026-01-26 14:11:00' \
--flashback
方式2
-
由于我修改的是远程测试数据库,没有权限使用binlog2sql操作数据库
-
同样的,还是先确定好日志文件,然后在终端使用mysqlbinlog导出日志文件,并查看内容。输入下面语句,时间范围则是前面看history log确定,输入后再输入数据库密码,就可以导出文件了。
-
mysqlbinlog --no-defaults -h 你的ip -P 你的数据库端口 -u 账号 -p --read-from-remote-server -v --base64-output=DECODE-ROWS --start-datetime="2026-01-26 12:20:00" --stop-datetime="2026-01-26 12:30:00" binlog.000184 > rollback_1220.txt- 导出文件后,通过vscode查看内容
-
找到对应区间的日志,查看日志,找到更新的区间,根据 # at去定位,修改的范围,比如我等一下修改为NONPAY,第二下修改为PAID。那日志记录则是原始status->NONPAY; NONPAY->PAID。所以我只要找到第一次修改的的日志范围,就可以将状态改为原样。
-
下面输入文件就是前面终端导出文件,两个POS就是我看导出的文件确认第一次update的日志范围(使用ctrl+f,输入update '表名’可以快速定位到开始位置,然后update…where…set为一条修改记录,where是原来的状态,set是更新的状态,@num对应字段,我的status是@13,update前有# at pos,这就可以确认区间)
-

-
然后用下面执行下面的py脚本,将set后的值改为where的值(更新前的字段值),导出sql文件,再去数据库执行就可以还原啦。
import sys input_file = 'rollback_1220.txt' output_file = 'rollback_by_pos.sql' # 你确定的位点区间 START_POS = 854396348 END_POS = 854402914 # 目标字段 STATUS_COL = "@13" ID_COL = "@1" results = [] with open(input_file, 'r', encoding='utf-8', errors='ignore') as f: in_range = False current_id = None current_status = None in_where = False for line in f: # 1. 识别位点,进入或退出区间 if line.startswith("# at"): pos = int(line.split()[2]) if pos >= START_POS and pos <= END_POS: in_range = True elif pos > END_POS: in_range = False break if not in_range: continue # 2. 在区间内寻找 topup_package_order 表的更新 # 识别 WHERE 部分 if "### WHERE" in line: in_where = True continue # 识别 SET 部分(表示 WHERE 结束,准备生成 SQL) if "### SET" in line: if current_id and current_status: sql = f"UPDATE topup_package_order SET order_status = '{current_status}' WHERE id = {current_id};" results.append(sql) # 重置当前块信息 current_id = None current_status = None in_where = False continue # 3. 在 WHERE 块中提取数据 if in_where: # 提取 ID if ID_COL + "=" in line.replace(" ", ""): parts = line.split("=") if len(parts) > 1: # 提取数字 val = "".join(filter(str.isdigit, parts[1])) if val: current_id = val # 提取原始状态 if STATUS_COL + "=" in line.replace(" ", ""): parts = line.split("=") if len(parts) > 1: # 提取引号内的内容 status_val = parts[1].strip().strip("'") current_status = status_val # 写入结果 with open(output_file, 'w', encoding='utf-8') as f: f.write("\n".join(results)) print(f"解析完成!") print(f"在位点 {START_POS} 到 {END_POS} 之间共提取到 {len(results)} 条 SQL。") if len(results) > 0: print(f"首条记录预览: {results[0]}") -
脚本也是ai写的,直接执行没什么问题,需要的话可以给ai修饰一下。
-
如果大家还有其他方式也可以分享在评论区哦!
更多推荐


所有评论(0)