MySQL使用binlog日志做数据恢复

2023-11-08

MySQL的binlog日志是MySQL日志中非常重要的一种日志,记录了数据库所有的DML操作。通过binlog日志我们可以进行数据库的读写分离、数据增量备份以及服务器宕机时的数据恢复。

定期备份固然可以在服务器发生宕机的时候快速的恢复数据,但传统的全量备份不可能做到实时,所以在发生宕机的时候,也会损伤一部分数据,如果这个时候开启了binlog日志,那么可以通过binlog来对没有做备份的这一阶段损失的数据进行恢复。如果了解Redis的朋友,可能想到了,Redis有两种持久化方式,分别是AOF和RDB。RDB就类似于MySQL的全量复制,AOF就类似于MySQL的binlog。

关于数据的恢复这里在说一点,既然binlog这么好,是不是开启了binlog就不需要定期做备份了呢,不要这样做。为什么呢,因为binlog的数据量非常大,另外就是使用binlog做数据的恢复性能会非常低。因为binlog是对操作的记录,比如某一时刻,我先插入了一条数据,然后将这条数据删除了,本身数据是没了,但有两条操作。如果是全量备份,肯定没有这条数据,如果使用binlog需要执行一条插入和一条删除操作,因此性能和文件大小都是比较大的。

啰嗦了一堆,下面说关于数据恢复的问题:

先创建一个数据库一个表,再插入两行数据

mysql> create database mytest;
ERROR 1007 (HY000): Can't create database 'mytest'; database exists
mysql> use mytest;
Database changed
mysql> create table t1(id int ,name varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t1 values (1,'xiaoming');
Query OK, 1 row affected (0.02 sec)

mysql> insert into t1 values (2,'xiaohong');
Query OK, 1 row affected (0.01 sec)

备份数据库

[mysql@t3-dtpoc-dtpoc-web04 mysql]$ cd /home/mysql/mysql/bin
[mysql@t3-dtpoc-dtpoc-web04 bin]$ ./mysqldump -uroot -p -B -F -R -x --master-data=2 mytest | gzip > /testdata/mysql/backup/bak_$(date +%F).sql.gz
Enter password: 
[mysql@t3-dtpoc-dtpoc-web04 bin]$ cd /testdata/mysql/backup/
[mysql@t3-dtpoc-dtpoc-web04 backup]$ ls
bak_2023-08-22.sql.gz

参数说明:

-B:指定数据库

-F:刷新日志 (执行一下flush logs)

-R:备份存储过程等

-x:锁表

--master-data:在备份语句里添加CHANGE MASTER语句以及binlog文件及位置点信息

这样呢,我们就把数据做了一个完整的备份。下面来删除数据库,然后通过备份数据进行恢复数据库。

[mysql@t3-dtpoc-dtpoc-web04 backup]$ gzip -d bak_2023-08-22.sql.gz
[mysql@t3-dtpoc-dtpoc-web04 backup]$ ls
bak_2023-08-22.sql

[mysql@t3-dtpoc-dtpoc-web04 bin]$ ./mysql -uroot -p < /testdata/mysql/backup/bak_2023-08-22.sql
Enter password: 

这样我们就把数据导入到库里了。

继续上面的操做,我们新增xiaoli和xiaozhao这两条数据,并把xiaozhao这条记录删除掉。

在删除之前,我们先来刷新binlog日志,生成一个新的日志,那么我们之后所要操做的内容都会被记录到新的日志文件中。(通过前面binlog日志的详细说明我们知道,每次刷新和服务重启的时候,都会生成一个binlog日志文件。)


mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)


我们注意,binlog的文件是0003,位置是在154,这两个信息很重要

下面我们来做插入和删除操作

mysql> insert into t1 values (3,'xiaoli'); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 values (4,'xiaozhao'); 
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+------+----------+
| id   | name     |
+------+----------+
|    1 | xiaoming |
|    2 | xiaohong |
|    3 | xiaoli   |
|    4 | xiaozhao |
+------+----------+
4 rows in set (0.00 sec)

这个时候我们应该是来查看一下binlog日志的状态,以便与我们一会来进行恢复到此状态,但是,真正的环境中我们并不知道这个状态,因此这里也就不去查看这个状态了,这个状态的值可以通过后面查看binlog日志文件来进行分析。下面我们开始误操作:

我们来把xiaozhao删除掉
mysql> delete from t1 where id=4;
Query OK, 1 row affected (0.00 sec)

这样数据就删除掉了,下面我们再来查看binlog的状态

show master status;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |     1776 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)


这个时候我们发现我删除操作是个错误的操作,要进行恢复,那么该如何恢复呢?这个时候我们就可以通过binlog的position来进行恢复。
在进行其他的处理之前,我们建议,马上再执行一次flush logs,也就是让出错的部分就集中在这么一个binlog日志文件中。

我们来查看0003的binlog日志。
mysql> show binlog events in 'mysql-bin.000003';
+------------------+------+----------------+-----------+-------------+----------------------------------------+
| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                   |
+------------------+------+----------------+-----------+-------------+----------------------------------------+
| mysql-bin.000003 |    4 | Format_desc    |    123454 |         123 | Server ver: 5.7.26-log, Binlog ver: 4  |
| mysql-bin.000003 |  123 | Previous_gtids |    123454 |         154 |                                        |
| mysql-bin.000003 |  154 | Anonymous_Gtid |    123454 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000003 |  219 | Query          |    123454 |         293 | BEGIN                                  |
| mysql-bin.000003 |  293 | Rows_query     |    123454 |         351 | # insert into t1 values (1,'xiaoli')   |
| mysql-bin.000003 |  351 | Table_map      |    123454 |         401 | table_id: 130 (mytest.t1)              |
| mysql-bin.000003 |  401 | Write_rows     |    123454 |         448 | table_id: 130 flags: STMT_END_F        |
| mysql-bin.000003 |  448 | Xid            |    123454 |         479 | COMMIT /* xid=191 */                   |
| mysql-bin.000003 |  479 | Anonymous_Gtid |    123454 |         544 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000003 |  544 | Query          |    123454 |         618 | BEGIN                                  |
| mysql-bin.000003 |  618 | Rows_query     |    123454 |         676 | # delete from t1 where name='xiaoli'   |
| mysql-bin.000003 |  676 | Table_map      |    123454 |         726 | table_id: 130 (mytest.t1)              |
| mysql-bin.000003 |  726 | Delete_rows    |    123454 |         773 | table_id: 130 flags: STMT_END_F        |
| mysql-bin.000003 |  773 | Xid            |    123454 |         804 | COMMIT /* xid=192 */                   |
| mysql-bin.000003 |  804 | Anonymous_Gtid |    123454 |         869 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000003 |  869 | Query          |    123454 |         943 | BEGIN                                  |
| mysql-bin.000003 |  943 | Rows_query     |    123454 |        1001 | # insert into t1 values (3,'xiaoli')   |
| mysql-bin.000003 | 1001 | Table_map      |    123454 |        1051 | table_id: 130 (mytest.t1)              |
| mysql-bin.000003 | 1051 | Write_rows     |    123454 |        1098 | table_id: 130 flags: STMT_END_F        |
| mysql-bin.000003 | 1098 | Xid            |    123454 |        1129 | COMMIT /* xid=193 */                   |
| mysql-bin.000003 | 1129 | Anonymous_Gtid |    123454 |        1194 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000003 | 1194 | Query          |    123454 |        1268 | BEGIN                                  |
| mysql-bin.000003 | 1268 | Rows_query     |    123454 |        1328 | # insert into t1 values (4,'xiaozhao') |
| mysql-bin.000003 | 1328 | Table_map      |    123454 |        1378 | table_id: 130 (mytest.t1)              |
| mysql-bin.000003 | 1378 | Write_rows     |    123454 |        1427 | table_id: 130 flags: STMT_END_F        |
| mysql-bin.000003 | 1427 | Xid            |    123454 |        1458 | COMMIT /* xid=194 */                   |
| mysql-bin.000003 | 1458 | Anonymous_Gtid |    123454 |        1523 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000003 | 1523 | Query          |    123454 |        1597 | BEGIN                                  |
| mysql-bin.000003 | 1597 | Rows_query     |    123454 |        1646 | # delete from t1 where id=4            |
| mysql-bin.000003 | 1646 | Table_map      |    123454 |        1696 | table_id: 130 (mytest.t1)              |
| mysql-bin.000003 | 1696 | Delete_rows    |    123454 |        1745 | table_id: 130 flags: STMT_END_F        |
| mysql-bin.000003 | 1745 | Xid            |    123454 |        1776 | COMMIT /* xid=196 */                   |
+------------------+------+----------------+-----------+-------------+----------------------------------------+
32 rows in set (0.00 sec)

我们看到delete_rows 结束点是1776这个点,起始点是在1523这个点,我们可以把操作的这些数据删除到我们上次备份的内容,然后通过执行binlog来进行恢复,当然恢复到1523这个点之前。
比如我上次备份的是整个数据库,我就可以把整个数据库删除,然后通过备份文件恢复,然后再通过binlog做增量恢复。这样数据就回来了。这里就不再进行删库了,我们直接演示使用binlog日志恢复数据的方法
语法如下

mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名

比如我们要把所有的操作都恢复(不包括我们的删除,我们知道删除是在1523点上):

[mysql@t3-dtpoc-dtpoc-web04 bin]$ ./mysqlbinlog /testdata/mysql/log/bin/mysql-bin.000003 --start-position 154 --stop-position 1523 | ./mysql -uroot -p mytest
Enter password: 

mysql> select * from t1;
+------+----------+
| id   | name     |
+------+----------+
|    1 | xiaoming |
|    2 | xiaohong |
|    3 | xiaoli   |
|    3 | xiaoli   |
|    4 | xiaozhao |
+------+----------+
5 rows in set (0.00 sec)

我们发现xiaozhao又回来了,当然了,这里多了一个xiali,是因为我之前并没有删除备份前的数据。当然了,我们在恢复的过程中可以选择只恢复xiaozhao这么一块内容

下面是binlog日志恢复中一些常用的参数
 

--start-datetime:从二进制日志中读取指定等于时间戳或者晚于本地计算机的时间

--stop-datetime:从二进制日志中读取指定小于时间戳或者等于本地计算机的时间 取值和上述一样

--start-position:从二进制日志中读取指定position 事件位置作为开始。

--stop-position:从二进制日志中读取指定position 事件位置作为事件截至

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL使用binlog日志做数据恢复 的相关文章

  • C#:SQL 查询生成器类

    在哪里可以找到好的 SQL 查询构建器类 我只需要一个简单的类来构建 SQL 字符串 仅此而已 我需要它用于 C 和 MySql 我真的不需要像 Linq 或 NHibernate 这样的东西 谢谢 由于 Google 将我引导至此页面 我
  • 如何将 MySQL 数据库更改为 UTC?

    我使用的是 Windows 7 对数据库方面的东西有点陌生 我尝试在 Google 上搜索如何将系统时区更改为 UTC 但文档有些高级 我不太确定如何更改此字段 在 my ini 文件的 mysqld 部分下 添加以下行 default t
  • 单行的总和值?

    我有一个 MySQL 查询 它返回由一系列 1 和 0 组成的单行 它用于进度条指示器 我现在在代码中对它进行求和 但我尝试对查询中的值求和 并意识到我无法使用 SUM 因为它们有很多列 但只有一行 有没有办法可以在查询中自动求和 就像这样
  • PHP 选择后立即删除

    我有一个 PHP 服务器脚本 它从 MySQL 数据库中选择一些数据 一旦我将 mysql query 和 mysql fetch assoc 的结果存储在我自己的局部变量中 我就想删除我刚刚选择的行 这种方法的问题在于 PHP 似乎对我的
  • MySql 最后插入 ID,连接器 .net

    我正在使用 MySql Connector net 我需要获取最后一个查询生成的插入 id 现在 我假设返回值是MySqlHelper ExecuteNonQuery应该是最后一个插入id 但它只返回1 我正在使用的代码是 int inse
  • 查询中列的顺序重要吗?

    当从 MySQL 表中选择列时 与表中的顺序相比 选择列的顺序是否会影响性能 不考虑可能覆盖列的索引 例如 您有一个包含行 uid name bday 的表 并且有以下查询 SELECT uid name bday FROM table M
  • MYSQL - 查找最近的前一天

    我可以以某种方式 不使用 PHP 找到一周中最近的前一天日期吗 Like 最近的上一个星期二的日期是哪一天 CURDATE INTERVAL WEEKDAY CURDATE wday IF WEEKDAY CURDATE gt wday 0
  • java mysql 准备好的语句

    我正在尝试使用 java 向数据库中进行简单的插入 它告诉我我的 sql 语法已关闭 但是 当我复制打印出来的字符串并将其放入 phpmyadmin 中的 sql 命令中时 它会正确执行该命令 并且我似乎无法弄清楚 java 中的字符串查询
  • 如何使用 MySQL 的 LOAD DATA LOCAL INFILE 在导入 CSV 时将字符串日期更改为 MySQL 日期格式

    我正在使用 MySQL 的 LOAD DATA LOCAL INFILE SQL 语句将数据从 CSV 文件加载到现有数据库表中 下面是一个 SQL 语句示例 LOAD DATA LOCAL INFILE file csv INTO TAB
  • Mysql 检索所有有限制的行

    我想检索特定用户的所有行 限制为 0 x 所以我只是想问是否有任何方法可以检索 mysql 中的所有行 而不调用返回 x 的 count id 的方法 而不重载现有函数 该函数在查询中根本没有限制 与我们的 string Relace 功能
  • 如何在Mysql中仅将不同的值从一个表复制到另一个表?

    我有一个大约 2 5GB 的 MySql 数据库 表 A 具有以下列 anoid query date item rank url 我刚刚创建了另一个仅包含列的表 b query and date 我想在查询列中插入所有不同的记录 及其各自
  • MySQL 使用 ALTER IGNORE TABLE 出现重复错误

    我的 MySQL 中有一个有重复项的表 我尝试删除重复项并保留一项 我没有主键 我可以通过以下方式找到重复项 select user id server id count as NumDuplicates from user server
  • 为什么我的 if 语句没有按我预期的方式工作?

    我正在尝试实现以下目标 我向我的 SQL 数据库询问使用SELECT FROM subjects 这样做之后我要求使用数组mysqli fetch assoc 在那之前一切都很好 现在的问题是 当我尝试在每个循环中修改 genero 的值
  • MySQL PHP邮政编码比较具体距离

    我试图找出比较一个邮政编码 用户提供的 和一大堆其他邮政编码 现在大约有 200 个邮政编码 之间的距离的最有效方法 相对于加载时间 但它会随着时间的推移而增加 我不需要任何精确的东西 只是在球场上 我下载了整个美国的邮政编码 csv 文件
  • 在 MySQL 中使用 COUNT 时如何返回 0 而不是 null

    我使用此查询返回存储在 sTable 中的歌曲列表以及存储在 sTable2 中的总项目数 SQL queries Get data to display sQuery SELECT SQL CALC FOUND ROWS str repl
  • 如何使用 vitess 仅对特定表进行分片

    我创建了一个包含三个表的未分片键空间 现在我想对前两个表的键空间进行分片 但不想对第三个表进行分片 如何才能做到这一点 Vitess 文档不包含任何与此相关的信息或示例 请帮忙 Thanks vitess 中的垂直分片与水平分片类似 您应该
  • 即使使用“autoReconnect=true”,MySql JDBC 也会超时[重复]

    这个问题在这里已经有答案了 有时 我的 Java Tomcat6 Debian Squeeze 应用程序无法与 MySql 服务器通信 Tomcat 应用程序位于前端服务器上 而 MySql 位于单独的 仅限 MySql 的机器上 一个典型
  • PDO PHP 连接,致命错误

    我的连接类 firstcode php class DB functions public db function construct try db new PDO mysql localhost dbname xxx charset ut
  • Bugzilla 中分离客户端的基本权限

    我正在尝试配置一个 Bugzilla 实例 这将允许我的客户登录并为其正在开发 维护的网站提交错误 例如 我创建了 2 个名为 TestProject TestProject2 的产品和一个名为 TestClient 的用户 我想要实现的是
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen

随机推荐

  • 怎么开发html5页面,一步一步教你如何开发h5页面

    我们现在要做一个简单的h5应用 包含登录 注册 修改密码 个人中心主页面 个人中心内页修改名称 个人中心修改手机号码 第一步 工具安装 我选择了能够辅助我们快速开发的light开发工具 light依赖node环境 所以首先要安装node h
  • Dropbox免费网盘高级使用技巧

    通过充分开发DropBox这个优秀的免费网络同步硬盘的功能 我们其实还可以实现很多常规玩法之外的高级应用 例如获得额外存储空间 或是拿来管理你的BT下载客户端等等 http db tt F6TkzeWG 通过此地址注册可得到2 25G 你也
  • LDAP服务器基础讲解

    LDAP用于管理和组织网络中的用户身份 权限和资源信息 LDAP在比赛中主要用于对samba和apache用户进行认证 想要完成上面这一点需要先对LDAP有一个初步的了解 LDAP中的域由目录项组成 每个目录项就相当于一个对象 目录项的结构
  • C语言简易选择题系统

    部分效果图 配置文件如下 加入新题库时 需要新建一个空文件 并把题目添加到新文件中 并把新文件名填入配置文件中 实现代码 File Name do test Sketch out A simple multiple choice syste
  • 为什么视觉系统对自动驾驶至关重要?

    自动驾驶汽车 AV 的承诺是 其将比人为控制的车辆安全得多 并大幅减少事故的发生 它需要众多技术的支持 才能在没有驾驶员驾驶的情况下运行 这些技术包括摄像头 激光雷达 雷达 超声波 车辆对一切 V2X 和全球定位系统 GPS 等 自动驾驶汽
  • Ant Design中使用Upload上传组件如何自定义文件列表展示位置

    软件环境 macOS Big Sur 11 1 React 16 12 0 Ant Design 4 10 0 实际效果 现有一个需求 是上传文件 点击浏览文件按钮 选中文件后 在按钮的上方显示 上传的文件列表 如下图所示 当前效果 目前使
  • 存储器容量的扩展

    存储器容量的扩展 一般而言 要构成一个存储器 一般需要多个存储芯片一起来构成 那么多个存储芯片是如何构成一个大的存储器来进行工作的呢 一般有如下三种方式 方式一 位扩展 增加存储字长 假设现在有1K 1024个 4位的存储芯片 容量为409
  • 为什么显示 from PyQt5.QtWebEngineWidgets import QWebEngineView ModuleNotFoundError: No module named 'PyQt5.QtWebEngineWidgets'

    这个错误通常是由于你的 Python 环境中缺少 PyQt5 QtWebEngineWidgets 模块引起的 这个模块是 PyQt5 库中的一个子模块 用于提供 WebEngine 功能 要解决这个问题 你需要安装 PyQt5 库 最简单
  • Flutter全屏效果切换使用 实现

    Flutter官方自带的splash启动页是在android或者ios的文件里面设置 但是不能添加倒计时之类的效果 自己做启动页需要全屏效果显示的时候 调用SystemChrome setEnabledSystemUIOverlays 这个
  • 开源最佳实践:Android平台页面路由框架ARouter

    摘要 为了更好地让开发者们更加深入了解阿里开源 阿里云云栖社区在3月1号了举办 阿里开源项目最佳实践 在线技术峰会 直播讲述了当前阿里新兴和经典开源项目实战经验以及背后的开发思路 在本次在线技术峰会上 阿里云资深开发工程师刘志龙分享了And
  • 【超简单方法】ubantu18.04.2安装最新显卡驱动

    1 检查工作 1 1去https www geforce cn drivers查找适合自己显卡的最新驱动版本 点击 开始搜索 然后 可以看出此时笔者的2060的最新显卡驱动版本为430 26 1 2 检查可安装驱动版本 接下来执行打开ter
  • ATF bl1 ufshc_dme_get/set处理流程分析

    ATF bl1 ufshc dme get set处理流程分析 UFS术语缩略词 1 ATF的下载链接 2 ATF BL1 ufshc dme get set流程 3 ufs总体架构图 3 1 UFS Top Level Architect
  • Collectors.collectingAndThen()

    Collectors collectingAndThen Java 8 流的新类 java util stream Collectors 实现了 java util stream Collector 接口 同时又提供了大量的方法对流 str
  • 赛灵思FPGA编程入门指南

    中英双语字幕精校版 赛灵思FPGA编程入门之新手指南第1集 什么是FPGA 现场可编程门阵列 FPGA概念 什么是FPGA 现场可编程门阵列 FPGA概念 本系列视频旨在为FPGA新人逐步讲解教程和基本概念 提供FPGA编程入门指导 帮助您
  • web程序员表白程序,三行情书

    Git项目地址 loveLetter 很久之前的作品 用JS和CSS3实现的 今天给大家分享一部分 若要见完整版 请点击右侧链接下载 程序员浪漫表白 三行情书 一等奖 JS CSS3 注 这是一个3D场景 在PC端的话还可以按住鼠标左键并拖
  • 数据库-sqlserver数据库迁移到mysql

    文章目录 前言 流程 前言 有时一些sqlserver的数据库需要迁移到mysql上 流程 管理员方式启动mysql的sqlYOG图形化界面 右键对象浏览器导入外部数据库 此处点下一步没有用的 需要先建立dsn 给要建立的dsn文件起个名字
  • 申请被拒模板 (五)

    这里只是模板 仅供学习 出现任何问题 与博主无关 Hi XXXX Thank you for your interest We appreciate the time you took to apply with us At this ti
  • h2 mysql 比较_h2 数据库时间比较

    时间比较的格式是 parsedatetime imp time yyyy MM dd hh mm ss en GMT gt parsedatetime 2012 06 07 00 00 00 yyyy MM dd hh mm ss en G
  • 多态、object类、package、Integer类、String和int类型之间的转换

    多态 多态即为事物存在的多种形态 多态存在的前提 要有继承关系 要有方法的重写 父类引用指向子类对象 多态中的成员访问特点 成员变量 编译看左边 父类 运行看左边 父类 成员方法 编译看左边 父类 运行看右边 子类 静态方法 编译看左边 父
  • MySQL使用binlog日志做数据恢复

    MySQL的binlog日志是MySQL日志中非常重要的一种日志 记录了数据库所有的DML操作 通过binlog日志我们可以进行数据库的读写分离 数据增量备份以及服务器宕机时的数据恢复 定期备份固然可以在服务器发生宕机的时候快速的恢复数据