动手实现一个mysql数据闪回小工具(一)

前言

开发一个自动数据库升级工具,实现一键回滚数据误操作或者升级回滚

基于mysql的binlog日志原理,动手实现了一个数据库升级小工具;可以通过执行binlog文件分析指定时间节点的日志,然后对应生成相应的dml回滚语句,最后执行回滚语句达到数据库快速回滚或者闪回功能。

解析binlog功能是通过开源项目-binlog2sql实现的,链接如下: danfengcao/binlog2sql: Parse MySQL binlog to SQL you want (github.com)

最后实现的效果如下:

场景

我们业务上有一个自动升级的场景,需要测试人员在升级的时候执行开发维护的脚本,长期以来都是手工执行,并且在升级失败后,还需要回滚,这样很不优雅

探究原理

我们知道,事务有原子性,只要一个事物没有提交,我们就能通过rollback进行回滚,那么rollback底层的原理是什么呢?那怎么回滚一个或者多个已经提交的事务数据?

能想到的就是通过日志来回滚的,我们先从mysql的日志入手,mysql是我固定使用的一个关系型数据库,它有undo-log,redo-log,bin-log,relay-log等等

事物回滚-Undo log

在dml操作的时候,会生成对应的回滚操作语句记录在undo log中。

当事物中某条语句执行失败的时候,mysql就会执行undo log中的回滚语句,将数据库中的数据回滚到事物执行前的样子。(怎么找到对应的undo log执行点的呢)--错误,并不会生成对应的回滚语句;

而是通过一种类似COW(copyonwrite写时复制技术)先复制原有表的数据到undolog,然后将原来数据的roll_ptr指针指向这个undolog记录,然后再回滚的时候用undolog中的记录覆盖原来表中的数据,就达到回滚的效果,但是如果多表和多数据量操作呢?

如果是insert操作,那么roll_ptr指向的就是null,那么回滚的时候就会用null覆盖原来的数据。

但是undo log在事物提交后会被清除?所以说undo log是实物回滚的原理,但是怎么实现数据回滚或者叫恢复呢?

故障恢复- Redo log

Redo log是数据库一种数据恢复日志,数据库在写入缓存前先会写到redo-log中,如果写入成功,就会给客户端响应写入成功,然后数据库再写入到缓存中,然后再刷新到磁盘上。

特点:

  1. Redo log是顺序写,将记录追加到文件的尾部。
  2. Redo 日志的磁盘文件个数,默认为2个,mysql通过来回写这两个文件的形式记录Redo-log日志,用两个日志文件组成一个环形,循环写
  3. 是InnoDB专享的
  4. 记录的是变更后的数据,主要实现故障情况下的数据恢复

由于Redo log是循环写,如果用redo log来实现数据回闪,那么数据会不全,并且redo log记录的是变更后的数据,回滚dml获取不到,所以不可行。

数据闪回- Bin log

那么相比Redo log,bin log一般记录了全量的修改日志,而且也是追加写的形式,如果我们不主动去删除磁盘的日志文件,并且磁盘的控件还足够,一般bin log日志文件都会在本地,所以在我们需要回闪数据的时候,有两种方式:

  1. 分析需要回退时间节点后的本地bin log, 根据对应的dml语句逆向生成回滚dml语句,然后执行,即可实现闪回。
  2. 复制bin log文件,然后拷贝出来一份,然后打开拷贝出来的文件,删除掉需要回滚时间节点后的bin log,然后再利用mysqlbinlog工具导出对应bin log文件的sql脚本,然后本地执行该脚本,即可实现闪回。

Bin log特点

  1. Bin log是所有引擎通用的
  2. Bin log也是追加写,但是只要磁盘空间足够,就会不断创建新的bin log磁盘文件写入。
  3. Bin log能记录变更的sql语句(选择row模式)
  4. Bin log用于数据灾备、同步

动手实现回闪小工具

工具还在完善中,目前实现如下:

相关推荐
C吴新科3 小时前
MySQL入门操作详解
mysql
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue4 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man4 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
Ai 编码助手5 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
白云如幻5 小时前
MySQL排序查询
数据库·mysql
苹果醋36 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
customer086 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源