Code Ease Code Ease
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档

神秘的鱼仔

你会累是因为你在走上坡路
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档
服务器
  • MySQL

    • 一文汇总数据库基础知识点!
    • 简单聊聊MySQL中的六种日志
    • 图解Mysql索引的数据结构!看不懂你来找我
    • 白话Mysql的锁和事务隔离级别!死锁、间隙锁你都知道吗?
    • 数据库分库分表扫盲,不会用也得知道概念
    • Mysql的索引调优详解
    • InnoDB的缓存池
    • InnoDB的插入缓冲和自适应哈希索引
    • MySQL监控工具
    • 删库了别跑路 你还应该学会如何恢复数据
      • 前言
      • 数据安全策略
      • 数据恢复流程演示
        • 创建数据
        • 备份数据
        • 模拟数据的删除
        • 进行数据恢复
        • 举一反三
      • 总结
  • Redis

  • MongoDB

  • 数据库系列
  • MySQL
CodeEase
2024-04-08
目录

删库了别跑路 你还应该学会如何恢复数据

作者:鱼仔
博客首页: codeease.top (opens new window)
公众号:Java鱼仔

# 前言

首先问大家一个问题,如果你上生产的代码在执行delete的时候跳过了where条件,或者执行update时忘记加where条件了,导致大量数据被删除或更新,你会如何处理?

上面的这些问题可能会导致很多数据被错误的更新或删除,当遇到这种情况时,用开玩笑的说法来说只能删库跑路,而更应该学会的是如何将这些数据恢复。

# 数据安全策略

为了保证数据的安全性,DBA一般会对数据库做下面这两个操作

  1. 对数据库进行定期备份:这个操作可能是一天一次,也可能是一周一次,频率越高,恢复的速度越快。
  2. 开启binlog日志:binlog日志可以做很多事情,比如在主从同步过程中,作为从库的数据来源,又比如在数据丢失的情况下做数据恢复。

通过下面的命令查看是否开启binlog日志

SHOW VARIABLES LIKE 'log_bin';
1

输出结果为on则代表binlog日志被开启

10-1.png

# 数据恢复流程演示

本次演示基于MySQL8.0.45,数据库引擎为InnoDB

# 创建数据

首先创建一张表,并往这张表里插入两条数据:

CREATE TABLE `test_person` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `school` varchar(255) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO `test`.`test_person` (`id`, `name`, `school`, `address`, `age`) VALUES (1, 'aa', 'testSchool', 'hz', 25);
INSERT INTO `test`.`test_person` (`id`, `name`, `school`, `address`, `age`) VALUES (2, 'bb', 'testSchool2', 'sh', 26); 

1
2
3
4
5
6
7
8
9
10
11
12

# 备份数据

接着模拟日常的备份动作,通过mysqldump命令进行数据备份

./mysqldump --single-transaction --flush-logs --source-data=2 --routines --opt -uroot -p test > backup.sql
1

下面是每个参数的含义:

--single-transaction:表示在备份过程中,使用单个事务来确保数据的一致性。

--flush-logs:表示在备份过程中,刷新日志文件,以便在备份完成后,日志文件中的内容不会影响到备份数据。

--source-data=2:表示在备份过程中,将主服务器的二进制日志位置信息也备份到文件中。这个参数比较重要,用于在恢复数据时找到位置信息。老版本叫做master-data

--routines:表示在备份过程中,备份存储过程和函数。

--opt:表示使用优化过的备份方式,以提高备份速度和减少备份文件的大小。

执行完成上面的命令之后,会发现多了一个backup.sql的文件

10-2.png

# 模拟数据的删除

接着在数据库中执行数据删除,模拟数据被误删

DELETE FROM test_person where 1=1
1

# 进行数据恢复

当发现数据被删除之后,此时就需要进行紧急数据恢复了,数据恢复的原理就是以定期备份文件为全量基础,加上binlog的增量数据,从而恢复数据到任何一秒。

首先需要从备份文件中找到最后的binlog写入位置:

cat backup.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
1

10-4.png

以上图为例,可以看到备份文件一直包含了mysql-bin.000007的157这个位置,意味着增量恢复只需要从157这个位置开始即可。 接着找到删除语句执行的位置

./mysqlbinlog --no-defaults -vv /usr/local/mysql/data/mysql-bin.000007 | grep -i -B 4 'delete from test_person'
1

10-3.png

从上面的命令可以看出,这条删除命令对应的binlog执行的位置是从318到428

从157到318的这中间的数据就是增量的数据,将这些数据整理成增量sql

./mysqlbinlog  --no-defaults --start-position=157 --stop-position=318 /usr/local/mysql/data/mysql-bin.000007 > backup_inc.sql
1

执行完成后,服务器上已经有backup.sql和backup_inc.sql两个文件了

分别执行下面两段sql进行数据恢复:

./mysql -uroot -p test < backup.sql
./mysql -uroot -p test < backup_inc.sql
1
2

再次运行查找语句会发现被删除的数据已经回来了。

# 举一反三

删除数据之后,可能还会有不少语句已经执行了,如果要将后续的数据也补上,要怎么实现呢?

也很简单,上面删除语句的执行位置是从318到428,那只需要将428之后的sql整理出来执行就行:

./mysqlbinlog  --no-defaults --start-position=428 /usr/local/mysql/data/mysql-bin.000007 > backup_inc2.sql
1

# 总结

这是一个值得学习的技能,也是一个最好永远不要用到的技能。不过了解数据恢复会加深对binlog日志的认识,也不错。

上次更新: 2025/04/29, 17:22:06
MySQL监控工具
入门redis看这一篇就够了

← MySQL监控工具 入门redis看这一篇就够了→

最近更新
01
AI大模型部署指南
02-18
02
半个月了,DeepSeek为什么还是服务不可用
02-13
03
Python3.9及3.10安装文档
01-23
更多文章>
Theme by Vdoing | Copyright © 2023-2025 备案图标 浙公网安备33021202002405 | 浙ICP备2023040452号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式