记录一次恢复 Mysql 中被 Update 操作覆盖的数据的过程

背景

最近开发的时候,Mysql 中配置了一条非常复杂且重要的数据记录,但是由于之后的一次不规范的 Update 操作,本想只更新其中一个字段值,结果却更新了整个记录,导致保存了 JSON 文本的字段值被初始成了默认值,数据丢失。从新配置该值太麻烦,于是踏上了数据恢复之路。

Binary Log

binlog 是 Mysql sever 层维护的一种二进制日志,与 innodb 引擎中的 redo/undo log 是完全不同的日志;其主要是用来记录对 mysql 数据更新或潜在发生更新的 SQL 语句,并以”事务”的形式保存在磁盘中;

binlog 虽然没有记录每次 query 操作,但是记录表结构和数据记录的每次变动操作,足以用来恢复数据。更多 binlog 的介绍请访问参考文章。

流程

查看 binlog 配置

登录 mysql,执行show variables like '%log_bin%';

1
2
3
4
5
6
7
8
9
10
11
12
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /www/server/data/mysql-bin |
| log_bin_index | /www/server/data/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+----------------------------------+
6 rows in set (0.00 sec)

检查 log_bin 是否为 ON 状态。如果是 OFF 就没戏了。
log_bin_basename 值是日志的文件基本路径,实际文件名会追加序号,例如 mysql-bin.000001,序号越大日志时间越新。

mysqlbinlog

mysqlbinlog 是 binlog 日志解析工具,需要用它进行日志操作。在安装了 mysql 数据库的情况下,如果直接执行 mysqlbinlog 提示没有该命令,就需要用绝对路径去执行了,在 mysql 安装目录的 bin 目录下,也可以通过 find / -name mysqlbinlog -print 查找。

mysqlbinlog 支持条件查询输出等,直接输出到控制台不方便查看,我这里直接输出到 sql 文件里,然后用 vim 查询相关字段,找到最新一次 update 操作,然后向前定位就能找到原数据了。

输入到 sql 的命令:

1
/www/server/mysql/bin/mysqlbinlog -v --base64-output=decode-rows mysql-bin.000007 --start-datetime="2019-06-9 9:00:00" --stop-datetime="2019-06-9 23:00:00" > output.sql

为了避免无关数据量太多,可以用开始时间、结束时间进行范围限定,也可以通过 query 类型限定。

结语

本文只是介绍了我的这种特殊场景下的 binlog 的使用,没有对 binlog 展开详细讲解,只是起到一个抛砖引玉的作用,请合理参考。

参考

MySQL Binlog 介绍

mysql 被删除的数据库恢复 binlog 恢复数据库