我在研究通过建立ddl表和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;

/

 

我在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;

 

我发现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开头的名字,同时原名也记录在其中。

那这个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

 

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

那么这个时候就需要用到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成一个特殊的名字的原因之一。




Related posts

coded by nessus
分享:  DeliciousGReader鲜果豆瓣CSDN网摘
Trackback

no comment untill now

Add your comment now

无觅相关文章插件