2.0解析系列 | OceanBase 2.0 之 Flashback 闪回功能

OB君:本文是 “ OceanBase 2.0 技术解析系列” 的第六篇文章。今天咱们来聊聊数据的持续可用,说说2.0中你们都很关心的“Flashback”闪回功能。更多精彩欢迎关注OceanBase公众号持续订阅本系列内容!

前言

数据库产品做为信息系统的重要组成部分,除了要高效的处理用户请求,还须要保证在各类异常状况下故障业务7*24的持续可用和数据的零丢失,本文的主要目的是总结和回顾一下传统数据库的常见故障,并介绍一下OceanBase做为分布式数据库在应对常见故障时的应对措施。mysql

常见数据库故障

分类系统故障

系统故障指数据库在运行过程当中,因为硬件故障、数据库软件或操做系统的漏洞、忽然停电等状况,致使系统异常,全部故障机器上正在运行的事务以非正常方式终止。sql

不一样于传统数据库的单点故障所致使的系统可用性问题,OceanBase做为分布式数据库为保证可用性提供了多种级别的容灾部署方案。针对机房级别容灾能力提供了同城三机房或两地三中心的部署方案,同时针对城市级别容灾能力提供了三地五中心部署方案。数据库

今年的云栖大会演示的网商银行三地五中心方案,模拟杭州城市级故障,26秒即完成容灾切换即体现了OceanBase针对城市级别故障的自愈能力。bash

同时针对极小几率的多数派故障,OceanBase和传统数据库同样提供全量+增量的备份恢复机制,当出现数据库异常故障时可使用离线备份恢复到全量备份到当前时间区间的任一时间点。为保障已提交事务数据不丢失,OceanBase采用和传统数据库同样的WAL(Write-Ahead Logging)方案,经过多数派先持久化事务日志的方式,保证提交事务不丢失。架构

介质故障

介质故障也称为硬故障,主要指数据库在运行过程当中,因为磁盘损坏、强磁干扰、天灾人祸等状况,使得数据库中的数据部分错误或数据丢失的一类故障。负载均衡

应对方案:针对介质故障致使的数据不一致问题,OceanBase会作两方面的校验。因为OceanBase是一个分布式数据库,同一份数据会有多个副本,大版本全量合并时会作多副本的一致性校验,每一个SSTable内部会拆分红2MB大小宏块,每一个宏块会计算Checksum。
当发现不一致时自动进行异常副本的替换。另外一方面主表和索引表的数据一样会作一致性校验,保障数据在主表和索引表之间的一致性。出于对数据正确性的敬畏,数据校验是OceanBase内部对本身的一道防火墙。运维

用户误操做

常见错误包括误连线上库后drop业务表, delete操做因为where条件缺失致使误删业务数据。分布式

应对方案:OceanBase经过多副本机制保证单点故障不影响业务,但仅有以上机制没法防范用户的误操做。常见的误删Database和Table方式,能够经过OceanBase的回收站机制实现恢复操做,而对于delete等dml方式的误操做,OceanBase能够经过数据库Flashback Query方式获取删除前快照实现误删数据恢复。下面会专门介绍传统数据和OceanBase应对用户误操做所作的工做。工具

主流数据库如何应对用户误操做

SQL Server 之 Database Snapshot


SQL Server经过DatabaseSnapshot机制实现快照查询,原理是首先在Database级别建立Snapshot,存储粒度为data-page级别,当Database快照对应的data-page第一次出现修改时,会将对应的前镜像存储于独立的sparse file中,当快照查询涉及到没有修改的data-page直接复用原始page便可。性能

MySQL 时间点恢复

MySQL没有单独机制存储数据块的前镜像,没有实现相似SQL Server的快照功能。 针对用户误操做只能经过数据库备份加上Binlog重放恢复到单一时间点,所以消耗的时间会比较久。有一些第三方工具好比binlog2sql , 能够经过设置Mysql数据库的binlog_format值为row,而且binlog_row_image参数设置为full,能够经过解析误Delete时间点的Binlog日志生成回滚SQL,在生产库中回放回滚SQL来实现数据库误操做恢复。

还有一种作法是经过备库延迟应用Binlog日志实现,这其实就是变相的使用离线备份加Binlog重放恢复,但能够节省全量备份恢复的时间。归根到底在数据库原生不存储数据前镜像的条件下只能经过备份加Binlog重放恢复用户数据。

Oracle Flashback 机制

Oracle做为功能最为完善的商业关系型数据库产品,提供了多种粒度的数据库闪回功能。
Flashback Query,FlashbackTable,Flashback Transaction Query和Flashback Versions Query都是经过直接从UNDO中读取数据前镜像构造历史快照,由于UNDO段是循环使用的,只要事务提交,以前的UNDO信息就可能被覆盖,从而致使闪回出现快照过旧的报错。

Flashback Drop是经过内部将原始Database或者Table重命名,并无物理删除。Flashback Database和FlashbackData Archive经过专有的数据前镜像来实现回滚操做。

整个Flashback家族中比较经常使用的功能为Flashback Query,Flashback Table和 Flashback Drop 。其中Flashback Table和Flashback Query 用于误Delete数据恢复, Flashback Drop 主要用于误Drop表的恢复。Flashback Database可能影响业务和丢失数据,通常只会在业务备库上开启,线上库不多使用。

OceanBase Flashback 功能介绍

OceanBase闪回功能和语法上总体上保持与Oracle兼容,但提供传统数据缺失的分布式容灾及多活能力。OceanBase 1.4版本已实现Table和Database级别的FlashbackDrop功能,在2.0版本实现Flashback Query功能,额外实现了Oracle缺失的Truncate Table的闪回功能。由于OceanBase和Oracle在设计思想方面的不一样,故实现方式上有本质的区别,下文具体介绍OceanBase的Flashback原理。

Flashback Query

OceanBase的闪回依赖于大版本合并的基线数据,和每次多版本的转储数据及内存MemTable中的全部事务修改记录,可闪回时间范围相似Oracle经过设置undo_retention最先可恢复时间,OceanBase会强制保留最先恢复时间点前一个大版本基线数据及后续全部的多版本转储SSTable。先简单介绍使用OceanBase Flashback Query的使用用例。

mysql> create table flash_query_table (id int);
Query OK, 0 rows affected (0.17 sec)

mysql> insert into  flash_query_table(id) values (1),(2),(3);
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> select now(),* from flash_query_table;

+---------------------+------+
| now() | id |
+---------------------+------+
| 2018-10-09 17:01:39 | 1 |
| 2018-10-09 17:01:39 | 2 |
| 2018-10-09 17:01:39 | 3 |
+---------------------+------+
3 rows in set (0.03 sec)

mysql> delete from flash_query_table where id<2;
Query OK, 1 row affected (0.04 sec)

mysql> select now(),* from flash_query_table;
+---------------------+------+
| now() | id   |
+---------------------+------+
| 2018-10-09 17:01:56 | 2 |
| 2018-10-09 17:01:56 | 3 |
+---------------------+------+
2 rows in set (0.02 sec)

mysql> select now(),* from flash_query_table 
as of timestamp to_timestamp('2018-10-09 17:01:40',
'yyyy-mm-dd hh24:mi:ss');

+---------------------+------+
| now() | id  |
+---------------------+------+
| 2018-10-09 17:02:01 | 1 |
| 2018-10-09 17:02:01 | 2 |
| 2018-10-09 17:02:01 | 3 |
+---------------------+------+
3 rows in set (0.03 sec)
复制代码

Flashback Query实现原理

OceanBase采用基线+增量的存储方式,内存中保存最新的行数据修改历史及对应的事务时间戳。同时当内存写满时会触发转储或者合并,转储的数据会保留上一次基线数据到当前转储时间点和每一个数据行的全部版本事务修改。MemTable一样会保留最新的事务多版本修改。
抽象下MemTable中存储逻辑结构以下:

说明:Han--> 4:s:2000000 表示4号事务修改行主键Han对应行的字段s值为2000000

MemTable在内存中维护了转储以后到最新时点的事务历史,将历史事务针对该行的操做按照事务提交时间组织成行操做链,新事务提交时会往行操做链尾部追加新的行操做。若是行操做链保存的历史事务过多,将影响读取性能,此时须要触发Compaction操做,融合这些历史事务并生成新的行操做链。但不会删除老的行操做链。所以Flashback Query只须要顺着内存中的反向指针往前回溯便可读取任一时点历史快照,根据Flashback Query闪回的位点分两种状况分析:

  • 闪回到转储以后的位点

须要合并基线+转储多版本+MemTable闪回位点对应快照

  • 闪回到基线以后转储以前的位点

须要合并基线+多版本转储对应闪回位点快照


回收站机制——flashback drop table / database,truncate table

OceanBase实现了回收站机制,从而防止用户误 drop table/database 的时候能快速恢复表数据。经过全局系统变量recyclebin 变量控制回收站功能的打开和关闭,on为打开(默认), off 为关闭。

索引单独drop进回收站比较特殊,当用户删除惟一索引后,对主表继续插入数据时,因为缺乏惟一性约束而致使当索引从回收站Flashback时,会出现惟一性冲突。针对此场景OceanBase替代方案为使用alter index invisible/visible, 设置索引在SQL层对用户不可见,存储层不受影响,惟一索引仍然作数据的惟一性检查。不支持drop索引进回收站。索引数据依赖主表,单独drop索引后经过重建恢复更方便。

OceanBase针对truncatetable特殊设计为truncate table=drop table+ create table,当开启回收站的状况下和drop table机制相似,但Flashback时须要采用rename to子句保证表名不冲突。而Oracle执行truncate table是不会保存undo信息,也不会挪进回收站,只能经过数据库备份恢复,此为OceanBase的一个设计优化点。

//还原回收站中的DATABASE
FLASHBACK DATABASE db_name TO BEFORE DROP [RENAME TO db_name];

//还原回收站中的TABLE, 注意这里db_name 能够将表flash到一个新的库下
FLASHBACK table_name TO BEFORE DROP [RENAME TO db_name.table_name];

//租户级别打开回收站机制
set global recyclebin=on

MySQL [test]> create table tb_drop(id int primary key,name varchar(5));
Query OK, 0 rows affected (0.07 sec)

MySQL [test]> insert into tb_drop values(1,'a'),(3,'c');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0 Warnings: 0

MySQL [test]> drop table tb_drop;
Query OK, 0 rows affected (0.02 sec)

MySQL [test]> select * from tb_drop;
+----+------+
| id | name |
+----+------+
| 1 | a    |
| 3 | c    |
+----+------+
2 rows in set (0.00 sec)

MySQL [test]> select gmt_create,
tenant_id,object_name,original_name 
from  oceanbase.__all_recyclebin 
where ORIGINAL_NAME='tb_drop';
+-----------------+-----------+------------------------+---------------+
| gmt_create     | tenant_id | object_name        | original_name |
+-----------------+-----------+------------------------+---------------+
| 2018-10-16 14:31:01.102840 | 1 | __recycle_$_10023_1_1539671461102752 | tb_drop       |
+-----------------+-----------+------------------------+---------------+
1 row in set (0.03 sec)

MySQL [test]> flashback table __recycle_$_10023_1_1539671461102752 to before drop;
Query OK, 0 rows affected (0.02 sec)
MySQL [test]> select * from tb_drop ;
+----+------+
| id | name |
+----+------+
| 1 | a   |
| 3 | c   |
+----+------+

2 rows in set (0.00 sec)
复制代码

实现原理以下

在开启回收站功能后,在原始的“DROP操做”的基础上会加一层包装。DROP涉及的对象会进入回收站,主要操做为修改对象的schema信息及在__all_recyclebin新增相关记录。

(1)被drop的表是系统表,那么直接删除,不进入回收站,不然进入步骤2;

(2)把被drop对象的schema信息中的OBJECT_NAME 改为__recycle$_gen_id ,其中gen_id的生成规则以下:
GEN_ID = cluster_id + tenant_id + schema_version 的方式组合
例如:__recycle_$_10023_1004_1539604687557424

(3)在__all_recyclebin表中插入被drop对象的信息。

还原操做涉及到两点,分别是对象的schema信息修改和删除内部表 __all_recyclebin 中的记录,具体步骤以下:

(1)检查用户是否具有相应的权限;

(2)从schema信息中OBJECT_NAME里面提取出原有对象的相关信息,修改对象的schema信息,主要是修改对象的名称,若是使用了RENAME TO语句指定了NEW_OBJECT_NAME,那么把名称改为NEW_OBJECT_NAME,不然改为ORIGINAL_NAME;

(3)若是发现当前TABLE所在的DATABASE已经被DROP掉,则FLASHBACK失败。若是成功则删除__all_recyclebin中相关的行记录。

总结OceanBase经过分布式多副本机制实现单点及少数派故障业务无感知,对于介质故障OceanBase经过多层Checksum机制保证数据的一致性,并自动实现数据修正。

对用户疏忽致使的误操做,OceanBase能够经过Flashback的轻量级方式实现数据快速恢复,或者经过数据库离线备份实现恢复到故障发生以前的位点。拥有OceanBase,线上误删数据库不再须要跑路了。

2.0解析系列文章

相关文章
相关标签/搜索