在oracle 12cR1版本中推出了一个新功能“In-Database Archiving”。这个选项允许将记录标记为不活动(称作归档记录)。当你把记录设置为归档记录后,你在Oracle的会话中就无法查看了。我曾经设计过这样的表。那个时候是通过字段标识来控制的,在一张数据表最后面增加一个字段isdelete,所有的删除都是更新操作,当我要对一条数据记录进行删除的时候,就默认发起update语句,把这条记录对应的isdelete更新为Y。然后查询只会查找isdelete=N的数据。这么做的好处就是我把历史删除的数据做了永久保留。对用户来说是透明的。要使用这个选项,必须在建表的时候指定row archival。或者建完表之后通过alter table来修改。
CREATE TABLE M1 (id NUMBER) ROW ARCHIVAL;
创建完表后,将自动会创建一个隐藏列ORA_ARCHIVE_STATE,专门用于记录活动的和不活动的数据。
SQL> SELECT column_id, table_name, column_name, hidden_column FROM dba_tab_cols WHERE table_name='M1' order by column_id; COLUMN_ID TABLE_NAME COLUMN_NAME HID ---------- ----------------------------------- ----------------------------------- --- 1 M1 ID NO M1 ORA_ARCHIVE_STATE YES
一旦新数据插入到表中,所有的记录默认都是active的,在会话中始终可见。 active的记录,ORA_ARCHIVE_STATE的值默认都为0,不是active的记录,ORA_ARCHIVE_STATE的值将为1。
SQL> INSERT INTO m1 SELECT LEVEL FROM dual CONNECT BY LEVEL <= 5; 5 rows created. SQL> commit; Commit complete. SQL> SELECT * FROM m1; ID ---------- 1 2 3 4 5 SQL> SELECT m1.*,ORA_ARCHIVE_STATE FROM m1; ID ORA_ARCHIVE_STATE ---------- -------------------- 1 0 2 0 3 0 4 0 5 0
如果我们要把123设置成不活动的记录,直接使用update进行更新,中间使用包DBMS_ILM.ARCHIVESTATENAME。
SQL> update m1 set ora_archive_state=DBMS_ILM.ARCHIVESTATENAME(1) where ID IN (1,2,3); 3 rows updated. SQL> commit; Commit complete.
此时我们在执行查询m1,可以看到只会显示4和5。
SQL> SELECT ORA_ARCHIVE_STATE, ID FROM M1; ORA_ARCHIVE_STATE ID -------------------- ---------- 0 4 0 5
当然我们也可以看到全部的记录,需要在session级别设置ROW ARCHIVAL VISIBILITY。
SQL> alter session set row archival visibility =all; Session altered. SQL> SELECT ORA_ARCHIVE_STATE, ID FROM M1; ORA_ARCHIVE_STATE ID -------------------- ---------- 1 1 1 2 1 3 0 4 0 5 SQL> alter session set row archival visibility =active; Session altered. SQL> SELECT ORA_ARCHIVE_STATE, ID FROM M1; ORA_ARCHIVE_STATE ID -------------------- ---------- 0 4 0 5
查看执行计划,你会发现,该语句默认的在谓词上加上filter(“M1”.”ORA_ARCHIVE_STATE”=’0′)的条件进行过滤操作。
SQL> select * from table(dbms_xplan.display()); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 3061007841 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 10075 | 3 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| M1 | 5 | 10075 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("M1"."ORA_ARCHIVE_STATE"='0') 17 rows selected.
当然要取消这个功能,只需要对alter table即可。
SQL> ALTER TABLE m1 NO ROW ARCHIVAL ; Table altered. SQL> select * from m1; ID ---------- 1 2 3 4 5
如果用ctas来创建一个备份表,默认会根据原表的情况来保持一致,不会只复制active的数据,我们来演示一下这个情况。
SQL> alter table m1 row archival; Table altered. SQL> update m1 set ora_archive_state=DBMS_ILM.ARCHIVESTATENAME(1) where ID IN (1,2,3); 3 rows updated. SQL> commit; Commit complete SQL> select * from m1; ID ---------- 4 5 SQL> create table m2 as select * from m1; Table created. SQL> select * from m2; ID ---------- 1 2 3 4 5
正如我们所看到的,即使我们在源表M1上启用了行归档功能,但在我们使用CREATE TABLE AS SELECT语句创建表时,它并没有传播到结果表。
Post a Comment