MySQL中闪回功能的方案讨论及实现

2025-03-21 13:50

本文主要是介绍MySQL中闪回功能的方案讨论及实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《MySQL中闪回功能的方案讨论及实现》Oracle有一个闪回(flashback)功能,能够用户恢复误操作的数据,这篇文章主要来和大家讨论一下MySQL中支持闪回功能的方案,有需要的可以了解下...

oracle有一个闪回(flashback)功能,能够用户恢复误操作的数据。本文讨论mysql中支持闪回的方案。

1、 闪回的目标

即使为了数据安全,我们搭建了主从。但实时主从备份只能防止硬件问题,比如主库的硬盘损坏。但对于误操作,则无能为力。比如在主库误删一张表,或者一个update语句没有指定where条件,导致全表被更新。当操作被同步到从库上后,则主从都“回天无力”。

线上或者测试环境经常出现的误操作总是让DBA同学那么闹心。

闪回的目的是要让数据库在commit之后,还能恢复到之前的某个状态,整库或指定的表。

这里我们讨论用binlog来实现闪回的方案。

2、 无米无炊一

恢复到之前的某个状态,是需要数据的。这数据可以是 a) 回滚步骤 或者 b) 操作之前的数据状态原文。

但我们知道,若使用statement,并没有上述需要的数据。试想binlog中记录了一句update t set f1=3 where id=3。怎么恢复呢?

因此,我们的第一个“米”,就是binlog必须是row based的。在row base下,binlog同时记录了更新前后的整行记录。

a)单个语句的闪回

了row base的binlog后,我们来分析一下怎么实现闪回。平时的DML无非三种操作,增删改,先说三种操作的日志格式。

一个语句分成两个event (实际上不止,其他可以忽略), 一个table_map event 和 一个Rows_log_event。Table_map event是一样的,主要看Rows_log_event。

每个Rows_log_event中包含event_type, 可选值为WRITE_ROWS_EVENT、UPDATE_ROWS_EVENT、DELETE_ROWS_EVENT。从宏名字就能看出用途。

对于insert和delete,event中包含了插入/删除的记录的所有字段的值(太爽了。。)

对于update操作,event中依次记录旧行, 新行的值。

因此我们看到,这些信息足够让我们对单个操作实现“逆操作”。

i. 对于insert操作,只需要把event_type改成DELETE_ROWS_EVENT;对于delete操作,改成WRITE_ROWS_EVENT

ii.  对于update操作,只需要把event中的旧行和新行值对调即可。

b)binlog的闪回

我们只需要把binlog文件反向执行,每个操作都执行逆操作即可。当然也不是所有的event都反转。Table_map event必须还是在Rows_log_event每个操作之前。目前的方案是用mysqlbinlog工具,增加一个flashback参数,输出结果为一个新的binlog文件――姑且叫做flashbacklog,这个flashbacklog顺序执行,www.chinasem.cn可制定某张表和执行到哪个pos,来实现数据库的闪回。 

3、 无米无炊二

上面我们说了DML的闪回方案。但对于DDL却无能为力,对于大多数的ddl,即使是row base格式,binlog中仍只记录语句本身。对于删表操作,只记录一个语句drop table t。仅凭这句话,无法还原表的数据。

虽然可以将一个drop table语句转换成先delete再删表,性能却会降低很多。这里我们用上面说道的另外一种可用数据:“操作前数据备份”。

按顺序我们先讨论怎么保存数据,再讨论怎么闪回。WAWdaECD

保存数据

先说DDL的分类。有一类DDL,是不需要重建表的,比如加非聚簇索引。这类操作其实不会丢数据,也是在原表上直接操作,对于我们“以恢复数据为目的”的闪回,是可以先忽略的。 另外一类,则是会影响到表数据的操作。比如

a)  Drop/truncate table

这两个操作直接把表数据清空。

b) &nbspythonp; Alter table add、drop、change column

这类操作的执行过程是,1) 按照新的表定义建立一个临时表tmpa,2) 将原表数据拷贝到临时表,3)将原始表改名tmpb,4)将tmpa改名为原表名,5)将tmpb删除。

我们分析上面的两个操作,都有一个“删除数据”的过程。

因此我们的保存数据方法就是:在删除的动作开始之前,把表数据备份起来,然后留一个空表,在空表上执行“删除”操作。

用一个库 #bak_database存放这些历史数据。

闪回

有了数据以后,我们就要想一个比较统一的方法来闪回。上面我们说了对于DML操作,可以通过反向执行所有逆操作来实现,对于语句里面的DDL,只能直接跳过。原因是一个DDL不一定有直接的逆操作。

因此我们的方案中要构造这种逆操作。Event_type增加一种FLASHBACK_EVENT。这类操作形式与Query_Event相同,都是简单的SQL语句,只是包含了将数据恢复的操作。

举例:

a)   对于altert table t add column 操作。

我们在操作的过程中将临时表tmpb,不删除,而是保存到 #bak_database.#bak_table_xxxxx (后缀用于去重),在我的patch中用当前的时刻(微秒)。

对于这个语句,我们生成两条FLASHBACK_EVENT,分别是 alter table `#bak_database`.`#bak_table_xxxxx` rename to `my_db`.`my_tbl`; 和 drop table  `my_db`.`my_tbl`;

这里的my_db和my_tbl分别为原来的库名和表名。

所以mysqlbinlog工具怎么处理FLASHBACK_EVENT这类event呢,直接执行就行了。(注意这两个event也是反向执行的,所以在恢复的时候是先删除`my_db`.`my_tbl`,再从#bChina编程ak_database恢复回来)

b)对于drop table操作

由于实际操作会把这个表删,只需要一个alter table `#bak_database`.`#bak_table_xxxxx` rename to `my_db`.`my_tbl`; 即可。

4、 演示

初始状态我们库中只有一个表 test.tb,两行

CREATE TABLE `tb` (
`c` int(11) NOT NULL DEFAULT '0′,
 `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;mysql> select * from tb;
+——+——+
| c    | d    |
+——+——+
|    1 |   10 |
|    2 |   20 |
+——+——+

模拟一个DML和一个DDL

insert into tb values(3,30);
alter table tb drop column d;  

这两个操作后在binlog文件中生成的结果如下

MySQL中闪回功能的方案讨论及实现

说明:

将mysqlbinloig中的其他信息去掉,其中红色框中为insert语句产生的binlog,在flashback工具中会被转化为delete操作。

两个蓝色框中的即为我们生成的FLASHBACK_EVENT。除了event_type与普通的query_event不同,还将库名+表名放在语句的前面,目的是为了flashback工具执行按表闪回的时候可以直接识别表名,不需要解析biWAWdaECDnlog语句。

紫色框中就是那个真正的DDL操作,在flashback工具中被忽略。

所以上面的binlog被flashback工具解析后的结果是两个DDL语句和一个delete操作,能够恢复到表的初始状态。

5、小结

这里讨论了MySQL闪回的一种方案.

增加一种新的event_type, 不会影响原来mysqlbinlog工具的使用;

备份即将删除的表,没有增加额外的操作,不会对正常操作性能造成影响(当然需要更多的存储空间)。

实际上我们上面还留了一个“空挡”没有讨论,在方案完成后补充。

涉及到MySQL server本身和mysqlbinlog这个工具两部分的修改,MySQL工具部分由@plinux同学实现。(其实如果不恢复DDL,可以只使用这个工具).  server部分的改动可以只部署slave,这样slave同时担负备份和闪回准备的功能。

到此这篇关于MySQL中闪回功能的方案讨论及实现的文章就介绍到这了,更多相关MySQL闪回内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于MySQL中闪回功能的方案讨论及实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153870

相关文章

MySQL使用binlog2sql工具实现在线恢复数据功能

《MySQL使用binlog2sql工具实现在线恢复数据功能》binlog2sql是大众点评开源的一款用于解析MySQLbinlog的工具,根据不同选项,可以得到原始SQL、回滚SQL等,下面我们就来... 目录背景目标步骤准备工作恢复数据结果验证结论背景生产数据库执行 SQL 脚本,一般会经过正规的审批

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

Redis中如何实现商品秒杀

《Redis中如何实现商品秒杀》:本文主要介绍Redis中如何实现商品秒杀问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录技术栈功能实现步骤步骤一:准备商品库存数据步骤二:实现商品秒杀步骤三:优化Redis性能技术讲解Redis的List类型Redis的Set

Redis如何实现刷票过滤

《Redis如何实现刷票过滤》:本文主要介绍Redis如何实现刷票过滤问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录引言一、概述二、技术选型三、搭建开发环境四、使用Redis存储数据四、使用SpringBoot开发应用五、 实现同一IP每天刷票不得超过次数六

Java利用poi实现word表格转excel

《Java利用poi实现word表格转excel》这篇文章主要为大家详细介绍了Java如何利用poi实现word表格转excel,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、每行对象类需要针对不同的表格进行对应的创建。package org.example.wordToEx

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

Java实现XML与JSON的互相转换详解

《Java实现XML与JSON的互相转换详解》这篇文章主要为大家详细介绍了如何使用Java实现XML与JSON的互相转换,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. XML转jsON1.1 代码目的1.2 代码实现2. JSON转XML3. JSON转XML并输出成指定的