前言
在当今互联网时代,我们频繁听闻删库跑路的新闻,删库跑路被判刑比比皆是。在企业核心业务系统等重要领域,数据的安全性显得尤为关键。尽管这些事件仅仅是小概率事件,但它们却揭示了一种潜在的威胁,需要我们警惕。作为12年的dba的老司机告诉你,除了删库、断电导致的文件损坏、勒索病毒,其实90%的原因都是由于应用误操作TRUNCATE导致的数据丢失。
一、Oracle的truncate
说到Oracle的truncate,老司机对它是又爱又恨,truncate既可以快速截断表数据,但也是高风险的操作。一旦误操作,在没有备份的情况下,又对表进行了更新操作,那么数据很有可能无法找回。
那么truncate,有哪些恢复的手段呢?我总结了10种类型。
- 数据库闪回
- DG
- 异机恢复
- TSPITR
- 12C RMAN的表级和表分区级
- FY_Recover_Data
- ODU
- GDUL
- SQL
- BBED修复元数据
Oracle truncate 原理
truncate table 是一种快速清空表内数据的一种方式,与delete方式不同,truncate只产生非常少的redo和 undo,就实现了清空表数据并降低表HWM的功能。truncate操作不修改表的数据块,只是通过字典基表以及段头和位图块的修改来实现快速清空表数据,释放的空间可以通过dba_free_space查询到
大致步骤如下:
- 对基表的操作
- 基表修改 obj,tab 的 dataobj#
- 修改 seg$ 的对应信息如(extents,blocks,hwmincr等等)
- 删除 tab_stats$ 对应对象的统计信息
恢复的主要思路:
- header+1获取data_object_id。有一种特殊情况:如果表只被truncate一次,那么上次的data_object_id和object_id是一致的。
- 通过dba_free_space获取所有free block。
- 通过dbms_rowid.rowid_create来创建rowid。
- 利用rowid来抽取数据。
通过rowid访问数据是不需要读取表的位图信息和段头,只通过读取基表信息完成解析,就可以直接访问rowid指定块的内容
恢复方法
下面根据几种方法,实操truncate恢复数据。
使用自己编写脚本恢复
使用FY_Recover_Data工具
使用ODU工具
使用GDUL工具
从上面几个方法可以可以看出,Oracle的truncate恢复异常的繁琐,并且应用没停止的情况下,数据被覆盖后,很难被恢复,大大增加了坐牢的风险。
Mogdb的truncate
- Mogdb的truncate基于闪回TRUNCATE原理:
可以恢复误操作或意外被进行truncate的表,从回收站中恢复被truncate的表及索引的物理数据。闪回truncate基于回收站机制,通过还原回收站中记录的表的物理文件,实现已truncate表的恢复。适用于误DROP、误TRUNCATE的表的恢复。用户通过配置回收站开关,并执行相应的恢复命令,可以将误DROP、误TRUNCATE的表找回。
相关参数
-
enable_default_ustore_table=on
开启默认支持Ustore存储引擎
-
undo_retention_time
设置undo旧版本保留时间。等同于允许闪回查询的时间跨度,超过该时间闪回查询可能会报restore point not found错误。
-
enable_recyclebin=on
打开回收站
-
recyclebin_retention_time=15min
设置回收站对象保留时间,超过该时间的回收站对象将被自动清理
实际案例
可以恢复误操作或意外被进行truncate的表,从回收站中恢复被truncate的表及索引的物理数据。闪回truncate基于回收站机制,通过还原回收站中记录的表的物理文件,实现已truncate表的恢复。适用于误DROP、误TRUNCATE的表的恢复。用户通过配置回收站开关,并执行相应的恢复命令,可以将误DROP、误TRUNCATE的表找回。
enable_default_ustore_table=on
开启默认支持Ustore存储引擎
undo_retention_time
设置undo旧版本保留时间。等同于允许闪回查询的时间跨度,超过该时间闪回查询可能会报restore point not found错误。
enable_recyclebin=on
打开回收站
recyclebin_retention_time=15min
设置回收站对象保留时间,超过该时间的回收站对象将被自动清理
mogdb=# create table t1(a int,b int,c int,d int) with (STORAGE_TYPE=USTORE);
CREATE TABLE
mogdb=# insert into t1 values(1,2,3,4),(21,22,23,24),(31,32,33,34);
INSERT 0 3
mogdb=# select * from t1;
a | b | c | d
----+----+----+----
1 | 2 | 3 | 4
21 | 22 | 23 | 24
31 | 32 | 33 | 34
(3 rows)
mogdb=# d+ t1
Table "public.t1"
Column | Type | Modifiers | Storage | Stats target | Description
--------+---------+-----------+---------+--------------+-------------
a | integer | | plain | |
b | integer | | plain | |
c | integer | | plain | |
d | integer | | plain | |
Has OIDs: no
Options: orientation=row, storage_type=ustore, compression=no
mogdb=# truncate table t1;
TRUNCATE TABLE
mogdb=# select * from t1;
a | b | c | d
---+---+---+---
(0 rows)
mogdb=# SELECT rcyname,rcyoriginname,rcytablespace FROM GS_RECYCLEBIN;
rcyname | rcyoriginname | rcytablespace
------------------------------+---------------+---------------
BIN$3F704EB8822$3169EAE0==$0 | t1 | 0
BIN$3F704EB8828$316A4FC8==$0 | t1 | 0
(2 rows)
mogdb=# timecapsule table t1 to before truncate;
TimeCapsule Table
mogdb=# select * from t1;
a | b | c | d
----+----+----+----
1 | 2 | 3 | 4
21 | 22 | 23 | 24
31 | 32 | 33 | 34
(3 rows)
总结:
MogDB中只需一步timecapsule table t1 to before truncate;就可以实现truncate恢复。
从此以后妈妈再也不用担心,truncate误操作数据而坐牢了。