当前位置: 首页 > 工具软件 > InnoSQL > 使用案例 >

innosql mysql_InnoSQL/MySQL DDL Flashback功能简介

都建树
2023-12-01

作者:网易数据库团队

在《删库不跑路!数据库误删有几种恢复方式?》一文中,我们曾提到处理数据库误删除的几种方法,其中一种是数据闪回(flashback),目前我们在开源实现的基础上,对DDL flashback方案进行了优化,解决了其存在的兼容性等问题。现对其进行简单介绍。

背景需求

Flashback概念最早出自Oracle,用于快速恢复用户的误操作,Flashback for MySQL是由阿里彭立勋于2012-5-2贡献的patch给MySQL官方5.5.18版本,此版本基于mysqlbinlog工具通过-B,--flashback参数对binlog中的DML逆操作生成闪回日志进行恢复,但此版本不支持DDL flashback。

随后2012-7-10阿里林晓斌贡献的patch支持DDL flashback,原理是通过rename的方式备份数据表,并增加FLASHBACK_EVENT event类型记录rename后的statement信息,通过mysqlbinlog工具-B,--flashback参数生成闪回log进行恢复。

DDL flashback版本存在三个问题:兼容性问题:引入了新的event类型FLASHBACK_EVENT,如果是主从复制场景,从库MySQL的版本未引入DDL flashback 功能时,从库回放relay-log时会因解析不了FLASHBACK_EVENT event而造成复制中断。

可维护性:回收库#bak_database的创建是写在系统库脚本中,随着mysqld的初始化进行创建,未记录binlog,同样如果从库版本没有引入DDL flashback功能,那么复制过来的rename语句会因为不存在#bak_database库而执行失败,造成主从不一致。

垃圾清理:#bak_database备份库没有进行垃圾回收,会造成磁盘空间冗余占用。

为此我们在InnoSQL 5.7和8.0版本上对DDL Flashback进行了优化改进,解决了上述问题,目前暂时支持drop/truncate两个常用的删除数据的操作,下面将简单介绍实现原理。

实现原理

总体思想是回收站原理,通过rename的方式将drop/truncate的表数据迁移至备库#bak_database中,通过mysqlbinlog工具-B,--flashback参数生成回滚语句进行数据恢复,并在mysqld启动时新增drop_flashback_table自动清理线程,定期自动清理#bak_database中的过期的备份数据,防止磁盘空间冗余占用。下面从这三部分功能的实现进行说明。

数据备份

在MySQL server层修改mysql_execute_command()函数中执行drop/truncate部分的代码,首先判断全局变量is_bak_database_created,如果为true,则说明#bak_database已经被创建,其他DDL操作直接使用备库,否则在DDL执行前先通过“CREATE DATABASE IF NOT EXISTS `#bak_database`”创建备库,这种方式可以通过主从复制同步到从库,这样避免了前述的问题2。

继续判断如果开启sql_flashback,则把执行语句修改成rename操作将数据备份到#bak_database库中,同时将对应的回滚语句通过注释的方式一起记录binlog,如下图1-3中黄色部分,分别列出了drop/truncate语句对应的binlog记录中rename操作和回滚操作内容。图1 truncate table语句binlog记录图2 drop table语句binlog记录图3 drop database语句binlog记录

数据恢复

通过mysqlbinlog工具-B,--flashback参数生成回滚语句进行数据恢复,-B参数是继承DML闪回实现版本,在打印binlog内容的函数Query_log_event::print中增加判断,如果mysqlbinlog开启-B参数并且event类型是QUERY_EVENT时,则解析/* FLASHBACK:xxxx */部分的内容,输出回滚语句进行数据恢复。

这样没有新增event类型,回滚操作通过记录在rename操作binlog注释/**/中,并通过mysqlbinlog解析来完成。避免了前述的问题1。

清理数据

在启动mysqld的过程中,新增drop_flashback_table线程,通过循环查询information_schema.tables中信息判断#bak_database库中是否存在备份表,如果存在,并且备份表的时间戳大于当前系统变量drop_flashback_timeout设置的过期清理时间,则对备份表执行drop操作进行清理,防止磁盘空间冗余占用。避免了前述的问题3。

参数说明

sql_flashback

开启/关闭DDL(drop/truncate)闪回功能,如:set sql_flashback = on/off,默认关闭,提供global和session 2个维度。并通过mysqlbinlog -B生成DDL回滚语句进行闪回。

例1:

create table test(a int);

insert into test values(1);

flush logs;

set sql_flashback=on;

drop table test;

mysqlbinlog -B mysql-bin.000003 > fb.sql

drop_flashback_timeout

设置备份库#bak_database中数据的过期时间,如:

set global drop_flashback_timeout=60;

默认过期时间是48小时,过期后备份数据将会被自动清理,可设置过期时间范围1min~365days。

例2:过期清理前#bak_database中的备份表。

客户端设置过期时间

set global drop_flashback_timeout=60;

60s后看过期表已经被清理。

mysql-err.log记录清理提示信息。

 类似资料: