删库不跑路,试试数据恢复

22 阅读4分钟

背景


Navicat 的工具栏有数据传输功能,可以对数据库进行结构和数据的同步

1751424835581.png

如果是数据库的全部表进行数据传输,执行的语句是

DROP DATABASE `xxx`;

CREATE DATABASE `xxx` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';

// 建表语句...
// 其他语句...

问题来了,在选择目标数据库时,因为连接名、数据库名称或者是操作者的疏忽的影响,可能会造成选择数据库错误的情况

要是赶上需要同步全库的表结构和表数据,那么目标数据库会被另一个错误的数据库覆盖,造成删库

解决方案


首先,找备份,从备份中恢复数据

要是没有备份怎么办呢?

那可以尝试使用mysqlbinlog进行处理(当然,前提是开启了binlog

  • MySql 5.7 及以下版本需要手动开启
  • MySQL 8.0 及以上版本默认开启

mysqlbinlog

MySQL 提供的一个命令行工具,用于解析、查看和管理 MySQL 的二进制日志(Binary Log,简称 binlog)

我们可以使用以下命令来查看数据库服务的mysqlbinlog信息

# 查看 `binlog` 是否开启
SHOW VARIABLES LIKE 'log_bin';

# 查看 `binlog` 文件格式
SHOW VARIABLES LIKE 'binlog_format';

# 查看 `binlog` 文件路径和基础名称
SHOW VARIABLES LIKE 'log_bin_basename';

# 查看当前正在使用的 `binlog` 文件
SHOW MASTER STATUS;

# 获取数据目录路径
SHOW VARIABLES LIKE 'datadir';

也可以在 MySql 数据目录下面查看mysql-bin.000001、mysql-bin.index、binlog.000001等文件

Mysql 数据目录,默认路径通常为

  •  /var/lib/mysql/(Linux)
  • C:\ProgramData\MySQL\MySQL Server X.X\Data(Windows)

若使用了Docker安装MySql,且未挂载数据卷,需要进入容器内部查看

具体操作

接下进入正题,怎么恢复?

其实一条命令就可以解决

mysqlbinlog 
--skip-gtids  
--database=xxx
--stop-datetime="2025-07-01 17:00:00" 
F:\binlog\binlog.000001 
F:\binlog\binlog.000002 
F:\binlog\binlog.000003 
F:\binlog\binlog.000004  | mysql  -u root -p --force
  • --skip-gtids:忽略 binlog 中的 GTID(全局事务标识符)
  • --database=xxx:仅解析与数据库 xxx 相关的操作,过滤其他库的日志
  • --stop-datetime="2025-07-01 17:00:00":解析 binlog 直到指定时间点(含该时间点)停止
  • 文件路径:可添加多个文件
  • --force:强制 MySQL 客户端忽略执行过程中的错误(如语法错误、主键冲突),继续执行后续 SQL

该命令是从建立数据库之初恢复所有数据,适用于无历史数据备份操作的情况(有历史数据备份操作情况可以指定--start-datatinmeposition),恢复时长视数据量大小而定 注意未执行完成不能退出,以免数据恢复不全

该命令使用了管道处理,无需中间文件。管道处理是指通过管道符 | 将一个命令的输出作为另一个命令的输入,形成数据流的连续处理链条。

若是Docker容器内部不便于操作mysqlbinlog

也可将日志文件同步到Windows机器,再用管理员方式打开mysqlbinlog.exe工具,进行操作


mysqlbinlog.exe 默认位置:

C:\Program Files\MySQL\MySQL Server 8.0\bin

扩展


如果要查看日志对应的sql文件,可以使用

mysqlbinlog 
--skip-gtids 
--base64-output=DECODE-ROWS 
--verbose 
--database=xxx 
F:\binlog\binlog.000001 
F:\binlog\binlog.000002 
F:\binlog\binlog.000003 
F:\binlog\binlog.000004 > F:\binlog\binlog_000001_000004.sql
  • --base64-output=DECODE-ROWS:将 ROW 格式的二进制日志解码为可读的伪 SQL 语句
  • --verbose 或 -v:增强输出可读性,添加注释(如字段类型)和完整的 SQL 语句。

-v-vv 和 -vvv 参数

  • -v(基础详细模式):将 ROW 格式的日志解码为伪 SQL 语句,但仅显示基本的列值(如 @1=1)和简单注释。
### UPDATE `test`.`users`
### WHERE
###   @1=1  /* INT meta=0 nullable=0 is_null=0 */
###   @2='Alice' /* VARSTRING(20) */
### SET
###   @1=1
###   @2='Bob'
  • -vv(增强详细模式):在 -v 基础上增加字段名和完整数据类型注释,输出更接近实际 SQL
### UPDATE `test`.`users`
### WHERE
###   `id`=1 /* INT meta=0 nullable=0 is_null=0 */
###   `name`='Alice' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */
### SET
###   `id`=1
###   `name`='Bob'
  • -vvv(最高详细模式):在 -vv 基础上进一步输出列的 字符集、排序规则 等高级元数据,适合深度分析
### UPDATE `test`.`users`
### WHERE
###   `id`=1 /* INT(11) meta=0 nullable=0 is_null=0 charset=utf8mb4 > collation=utf8mb4_general_ci */
###   `name`='Alice' /* VARCHAR(20) meta=20 nullable=1 is_null=0 charset=utf8mb4 > collation=utf8mb4_general_ci */
### SET
###   `id`=1
###   `name`='Bob'

!注意

不推荐将binlog文件转化为 sql文件,再导入文件到数据库方法。
ROWbinlog文件 默认数据格式)来说,无法转化正确的insert、update语句,转化的语句是伪sql,并不是可执行sql