Oracle回收站表闪回机制研究

 

总体概况

在数据库中创建DDL 触发器和DDL 表时,发现在drop 表的时候,oracle 内部会先把表给rename 后再drop 到回收站内。那这个rename 的操作有什么特殊的含义,接下来就是研究过程

 

创建DDL 表和DDL 触发器来跟踪drop 表的过程

我在研究通过建立ddl 表和ddl 触发器来记录数据库中ddl 的操作日志的时候发现一个有意思的事:

 

1. 创建DDL 表和DDL 触发器

---- 存储DDL 语句的表

create table sys.my_audit_ddl(

opertime timestamp PRIMARY KEY,

ip varchar2(20),

hostname varchar2(30),

operation varchar2(30),

object_type varchar2(30),

object_name varchar2(30),

sql_stmt clob,

db_schema varchar2(30)

);

 

---- 捕获DDL 语句的触发器

CREATE OR REPLACE TRIGGER sys.trg_my_audit_ddl

after ddl ON DATABASE

DECLARE

PRAGMA AUTONOMOUS_TRANSACTION;

n NUMBER;

stmt clob := NULL;

sql_text ora_name_list_t;

BEGIN

n := ora_sql_txt(sql_text);

FOR i IN 1 .. n LOOP

stmt := stmt || sql_text(i);

END LOOP;

INSERT INTO sys.my_audit_ddl

(opertime, ip, hostname, operation, object_type, object_name, sql_stmt,db_schema)

VALUES

(systimestamp,

sys_context('userenv', 'ip_address'),

sys_context('userenv', 'terminal'),

ora_sysevent,

ora_dict_obj_type,

ora_dict_obj_name,

stmt,

user

);

COMMIT;

END;

/

 

2. test 用户下建一张test

create table test (

name varchar2(20),id number(2));

 

sys 用户查询那张ddl 记录表:

SQL> select SQL_STMT,OPERTIME from sys.my_audit_ddl;

 

SQL_STMT                                            OPERTIME

----------------------------------                  ------------------------------

create table test (                                      04-AUG-17 01.46.50.762982 PM

name varchar2(20),id number(2))

 

 

可以看到创建的记录被记录下来。

 

test 用户删除这张test 表(不加purge ):

drop table test;

 

3. 发现ddl 记录的过程中,多了一行

SQL> select SQL_STMT,OPERTIME from sys.my_audit_ddl;

 

SQL_STMT                                                                     OPERTIME

-------------------------------------------------------------------------- -- ------------------------------

create table test (                                                                04-AUG-17 01.46.50.762982 PM

name varchar2(20),id number(2))

 

ALTER TABLE "TEST"."TEST" RENAME TO "BIN$VegNdsxaqv7gU2UoqMD5iA==$0"        04-AUG-17 01.48.56.035327 PM

drop table test                                                                  04-AUG-17 01.48.56.149173 PM

 

在删除这张表进入回收站之前,会先将这张表更改名字,然后再删除这张表。

去回收站内查看:

SQL> select owner,object_name from dba_recyclebin;

OWNER                          OBJECT_NAME                    ORIGINAL_NAME

------------------------------ ------------------------------ ----------------------

TEST                           BIN$VegNdsxaqv7gU2UoqMD5iA ==$0  TEST

 

 

可以看到,在回收站内看到的表名,被改成BIN 开头的名字,同时原名也记录在其中。

4. 那这个object_name 有什么用呢?

我们在使用flashback table 的时候,语句一般是这样的:

flashback table test to before drop;

 

这个时候,回收站内的test 表,会被还原到原用户下。

但如果如果一个用户,连续两次删除了一张同名表呢?

还原的时候指定这两张同名表的时候,回收站会默认还原距离当前时间最近被删除的一张表:

 

SQL> select object_name,original_name,droptime,dropscn from user_recyclebin;

 

OBJECT_NAME                    ORIGINAL_NAME                    DROPTIME               DROPSCN

------------------------------ -------------------------------- ------------------- ----------

BIN$VehKONsSsmrgU2UoqMAAqA==$0 TEST01                           2017-08-04:14:12:00    1171519

BIN$Vek/0SbO3ODgU2UoqMBrzQ==$0 TEST01                           2017-08-04:15:22:30    1175274

 

SQL>flashback table test01 to before drop;

 

SQL> select object_name,original_name,droptime,dropscn from user_recyclebin;

 

OBJECT_NAME                    ORIGINAL_NAME                    DROPTIME               DROPSCN

------------------------------ -------------------------------- ------------------- ----------

BIN$VehKONsSsmrgU2UoqMAAqA==$0 TEST01                           2017-08-04:14:12:00    1171519

 

5. 那我们如果想还原的不是这张距离时间最近的表呢?

那么这个时候就需要用到object_name 了。

通过指定object_name ,我们可以还原任意一张表:

 

SQL> select object_name,original_name,droptime,dropscn from user_recyclebin;

 

OBJECT_NAME                    ORIGINAL_NAME                    DROPTIME               DROPSCN

------------------------------ -------------------------------- ------------------- ----------

BIN$VehKONsSsmrgU2UoqMAAqA==$0 TEST01                           2017-08-04:14:12:00    1171519

BIN$Vek/0SbO3ODgU2UoqMBrzQ==$0 TEST01                           2017-08-04:15:22:30    1175274

 

SQL>flashback table “ BIN$VehKONsSsmrgU2UoqMAAqA==$0” to before drop;

这就是在drop 的时候,为什么oracle 会先把表给rename 成一个特殊的名字的原因之一。


请使用浏览器的分享功能分享到微信等