目录
1. 背景
2.测试环境准备
3.基于类似windows系统回收站的恢复
4.基于MVCC多版本的数据恢复
5.总结&反思
1. 背景
openGauss闪回功能能够有选择性的高效撤销一个已提交事务的影响,从人为错误中恢复。在采用闪回技术之前,只能通过备份恢复、PITR等手段找回已提交的数据库修改,恢复时长需要数分钟甚至数小时。采用闪回技术后,恢复已提交的数据库修改前的数据,只需要秒级,而且恢复时间和数据库大小无关。适用于:
1)误删除表的场景;
2)需要将表中的数据恢复到指定时间点或者CSN。
闪回支持两种恢复模式:
- 基于MVCC多版本的数据恢复:适用于误删除、误更新、误插入数据的查询和恢复,用户通过配置旧版本保留时间,并执行相应的查询或恢复命令,查询或恢复到指定的时间点或CSN点。
- 基于类似windows系统回收站的恢复:适用于误DROP、误TRUNCATE的表的恢复。用户通过配置回收站开关,并执行相应的恢复命令,可以将误DROP、误TRUNCATE的表找回。
看起来不错,谁还没有个手滑误操作的时候。搓搓小手,试一试。
2.测试环境准备
软硬件环境:
- 华为云服务器+openGauss企业版3.0.0 + openEuler20.03
- Data Studio (这个为了方便执行SQL的,非必须)
参数设置:
- 启用回收站参数enable_recyclebin。
- 设置回收站对象保留时间recyclebin_retention_time,超过该时间的回收站对象将被自动清理。单位为s,最小值为0,最大值为259200。
- 设置内存中可分配的undo zone数量undo_zone_count,0代表禁用undo和Ustore表,建议取值为max_connections*4
gs_guc set -N all -I all -c "undo_zone_count=16384"
gs_guc set -N all -I all -c "enable_recyclebin=on"
gs_guc set -N all -I all -c "recyclebin_retention_time=30min"
gs_om -t restart
3.基于类似windows系统回收站的恢复
回收站的方式有两种:
- 闪回TRUNCATE:可以恢复误操作或意外被进行truncate的表,从回收站中恢复被truncate的表及索引的物理数据。闪回truncate基于回收站机制,通过还原回收站中记录的表的物理文件,实现已truncate表的恢复。
- 闪回DROP:可以恢复意外删除的表,从回收站(recyclebin)中恢复被删除的表及其附属结构如索引、表约束等。闪回drop是基于回收站机制,通过还原回收站中记录的表的物理文件,实现已drop表的恢复。
现在开始操作。
- 建表、插入测试数据。
create SCHEMA tpcds;
DROP TABLE IF EXISTS tpcds.reason_t2;
CREATE TABLE tpcds.reason_t2
(
r_reason_sk integer,
r_reason_id character(16),
r_reason_desc character(100)
) with(STORAGE_TYPE=USTORE);
INSERT INTO tpcds.reason_t2 VALUES (1, 'AA', 'reason1'),(2, 'AB', 'reason2'),(3, 'AC', 'reason3');
select * from tpcds.reason_t2; 目前为止都很正常,返回数据也是对的。 r_reason_sk | r_reason_id | r_reason_desc
-------------+------------------+------------------------------------------------------------------------------------------------------
1 | AA | reason1
2 | AB | reason2
3 | AC | reason3
(3 rows) - 然后,关键点来了。删除数据然后看能不能闪回。
TRUNCATE TABLE tpcds.reason_t2;
select * from tpcds.reason_t2;
--现在查询表是空的,没错。
--执行闪回
TIMECAPSULE TABLE tpcds.reason_t2 to BEFORE TRUNCATE; oh ,翻车鱼来了,我得到了一个error :“ERROR: timecapsule does not support astore yet” 不支持astore?? 嗯,看了下注意事项,没有说到这个。后来查看管理员指南,在特性描述倒是说了“ASTORE引擎暂不支持闪回功能。备机不支持闪回操作。”在开发者指南 CREATE TABLE部分找到这么一句话。 STORAGE_TYPE:指定存储引擎类型,该参数设置成功后就不再支持修改。不拉不拉 ,不指定表时,默认是Append-Only存储。因此,由于openGauss建表默认为astore模式,是不支持闪回的。所以,现在需要修改建表脚本为ustore模式。 DROP TABLE IF EXISTS tpcds.reason_t2;
CREATE TABLE tpcds.reason_t2
(
r_reason_sk integer,
r_reason_id character(16),
r_reason_desc character(100)
) with(STORAGE_TYPE=USTORE);
INSERT INTO tpcds.reason_t2 VALUES (1, 'AA', 'reason1'),(2, 'AB', 'reason2'),(3, 'AC', 'reason3');
select * from tpcds.reason_t2;
--清空数据
TRUNCATE TABLE tpcds.reason_t2;
--确认清空成功了
select * from tpcds.reason_t2;
--闪回到清空前
TIMECAPSULE TABLE tpcds.reason_t2 to BEFORE TRUNCATE; - 再查询一下,数据回来了。测试成功
openGauss=# select * from tpcds.reason_t2;
r_reason_sk | r_reason_id | r_reason_desc
-------------+------------------+------------------------------------------------------------------------------------------------------
1 | AA | reason1
2 | AB | reason2
3 | AC | reason3
(3 rows) - 再测试下DROP功能。
DROP TABLE tpcds.reason_t2;
select * from tpcds.reason_t2;
--因为表已经drop了,所以理所当然的报错。然后继续闪回
TIMECAPSULE TABLE tpcds.reason_t2 to BEFORE DROP;
--重新查询,表又恢复了。
openGauss=# select * from tpcds.reason_t2;
r_reason_sk | r_reason_id | r_reason_desc
-------------+------------------+------------------------------------------------------------------------------------------------------
1 | AA | reason1
2 | AB | reason2
3 | AC | reason3
(3 rows) drop掉的表和数据也都回来了。奈斯
4.基于MVCC多版本的数据恢复
- 依旧是建表插数据。(PS:其实我在这里又翻车了一次,开始建表时又没有指定STORAGE_TYPE=USTORE,得到了一个error “ERROR: timecapsule feature does not support heap table”。想测试该特性的小伙伴还是小心这个点。)
drop table if EXISTS tpcds.time_table;
create table tpcds.time_table(idx integer, snaptime timestamp, snapcsn bigint, timeDesc character(100)) with(STORAGE_TYPE=USTORE);
INSERT INTO tpcds.time_table select 1, now(),int8in(xidout(next_csn)), 'time1' from gs_get_next_xid_csn();
INSERT INTO tpcds.time_table select 2, now(),int8in(xidout(next_csn)), 'time2' from gs_get_next_xid_csn();
--出去接杯水再回来
INSERT INTO tpcds.time_table select 3, now(),int8in(xidout(next_csn)), 'time3' from gs_get_next_xid_csn();
--去拿了包薯片
INSERT INTO tpcds.time_table select 4, now(),int8in(xidout(next_csn)), 'time4' from gs_get_next_xid_csn();
select * from tpcds.time_table; - OK,现在重新查询
delete tpcds.time_table;
SELECT * FROM tpcds.time_table TIMECAPSULE TIMESTAMP to_timestamp('2022-05-17 16:17:20.311176','YYYY-MM-DD HH24:MI:SS.FF');
结果正确,已经可以重新查询到指定时间之前的数据了。3 和 4 因为是16:17:20之后才插入的,所以不能查到。 - 再测试下根据CSN的闪回能力。
-
SELECT * FROM tpcds.time_table TIMECAPSULE CSN 351356; - 最后清空回收站。
openGauss=# purge recyclebin;
PURGE RECYCLEBIN
5.总结&反思
功能测试基本完成,特性还是很不错的,操作下来也比较简单。现在反思下我遇到的两个问题,都是因为表的存储方式为astore,而闪回特性不支持该种类型导致的,建表时指定为ustore就可以解决。so,有没有办法默认建表时就是ustore存储呢?继续翻看产品文档,是有参数可以设置的。
gs_guc set -N all -I all -c "enable_default_ustore_table=on" ?
这样在实验开始前设置好就无需再建表时手动指定存储格式了。但是,为什么数据库的默认值给的是astore呢?补课学习下ustore和astore的差异。
openGauss内核当前使用的行引擎采用的是Append Update(追加更新)模式,该模式在INSERT、DELETE、HOT UPDATE(页面内更新)的场景下有较好的表现。主要面向通用的在线交易处理类业务应用场景,适合高并发、小数据量的单点或小范围数据读、写操作。astore为行存储格式,向上提供元组形式的读、写;向下以页面为单位通过可扩展的介质管理器对存储介质进行读、写操作;并通过页面粒度的共享缓冲区来优化读、写操作的效率。
astore存储格式为追加写优化设计,其多版本元组产生和存储方式下图所示。
当一个更新操作将v0版本元组更新为v1版本元组之后,如果v0版本元组所在页面仍然有空闲空间,则直接在该页面内插入更新后的v1版本元组,并将v0版本的元组指针指向v1版本的元组指针。在这个过程中,新版本元组以追加写的方式和被更新的老版本元组混合存放,这样可以减少更新操作的I/O开销。然而,需要指出的是,由于新、老版本元组是混合存放的,因此在清理老版本元组时需要的清理开销会比较大。因此,astore存储格式比较适合频繁插入、少量更新的业务场景。详细内容参考:
openGauss数据库源码解析系列文章——存储引擎源码解析(一)
ustore属于In-place Update更新模式,中文意思为:原地更新,是openGauss内核新增的一种存储模式。astore对于非HOT UPDATE场景,垃圾回收不够高效。ustore存储模式提供“原地更新”能力,主要思路是将最新版本的“有效数据”和历史版本的“垃圾数据”分离存储。将最新版本的“有效数据”存储在数据页面上,而单独开辟一段undo(回滚)空间,用于统一管理历史版本的“垃圾数据”,因此数据空间不会由于频繁更新而膨胀,垃圾回收效率更高。通过NUMA-aware的undo子系统设计,使得undo子系统在多核平台上高效扩展。同时通过对元组和数据页面结构的重新设计,减少存储空间的占用。采用多版本索引技术,解决索引膨胀问题,彻底去除autovacuum(垃圾清理线程)机制,提升存储空间的回收复用效率。当前USTORE存储引擎不支持极致RTO回放模式。对于主机,在recovery_parse_workers参数设置大于1的情况下,创建USTORE存储引擎的表将返回报错;对于备机,如果数据库中已经包含USTORE表,那么后续如果再打开极致RTO功能,可能会导致回放失败和报错,严重情况下甚至可能导致备机数据损坏(这种情况下需要执行备机重建进行修复)。详细内容参考
openGauss数据库源码解析系列文章——存储引擎源码解析(四)
以上就是我对openGauss 3.0.0版本闪回特性的一些基本验证,希望能帮到正在看的你~
|