Playing with Flashback Data Archive on 11GR2

viadeazhu發表於2009-10-12

此前所寫的《11G Flashback Data Archive新特性的研究》是基於 環境:

http://space.itpub.net/15415488/viewspace-615982

 

最近11GR2釋出,於是趕快在自己的RedHat EL5上安裝了,於是本文主要以一種天馬行空撰文的方法,聊一聊自己Playing with FBDA的一段經歷。

其中有一些是危險的操作,主要來滿足個人對FBDA的好奇,希望不要在生產環境模仿。

 

     一.11GR2 NF PPT號稱的為FBDA tracked table增加了更多DDL支援其實在是(提前)忽悠大家的。

讓我們來看看PPT裡所講的:
ALTER TABLE ADD COLUMN was supported in Oracle Database 11g Release 1.
In Oracle Database 11g Release 2, the following DDL operations are supported:
  Dropping of columns and partitions
  Modifying and renaming columns
  Renaming tables
  Truncating tables and partitions

那麼在11.2.0.1上事實真是如此麼?

1.1 drop column仍然不支援:
SQL> show parameter compatible

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
compatible                           string      11.2.0
SQL> alter table haotest drop column object_id;
alter table haotest drop column object_id
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

1.2 drop partition仍然不支援:
SQL> create table haopar(id number,name varchar2(30))
  2  partition by range (id)
  3  (PARTITION part1 VALUES LESS THAN (100),
  4  PARTITION part2 VALUES LESS THAN (maxvalue)
  5  ) tablespace assmtbs;

Table created.

SQL> alter table haopar flashback archive haofbda;

Table altered.
SQL> alter table haopar drop partition part1;
alter table haopar drop partition part1
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

1.3 modify column仍然不支援
SQL> alter table haotest modify object_id2 number(1,1);
alter table haotest modify object_id2 number(1,1)
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

1.4 rename column仍然不支援

SQL> alter table haotest rename column object_id2 to object_id3;
alter table haotest rename column object_id2 to object_id3
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

1.5 rename table至少早在11.1.0.6就支援了,所以現在11.2支援也不算新特性。
1.6 truncate table仍然不支援
SQL> truncate table haotest;
truncate table haotest
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

1.7 truncate partition仍然不支援
SQL> ALTER TABLE haopar truncate PARTITION part1;
ALTER TABLE haopar truncate PARTITION part1
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table

綜上,至少在11.2.0.1 for linux on X86上,
new feture PPT所述的更多支援DDL仍然不支援。
但我更原因相信這些正在將來的11.2版本上會支援,
但目前我姑且認為是提前的忽悠。

    二.FBDA bug全集

我很幸運在玩的時候,幾乎經歷了所有的Bug。

Metalink上幾乎沒寫任何的workaround,這讓我感到不敢在11.2base version使用FBDA。

2.1 Bug:FLASHBACK DATA ARCHIVE COSUMES HIGH CPU
    Bug No: 7028762

在history table建立前,將已經enable FBDA的table給disable FBDA後,FBDA後臺程式佔用大量CPU。

由於在我破本本是單核的,所以,常常看到它佔用70%以上的CPU。

SQL> create flashback archive haofbda2
  2  tablespace fbdatbs
  3  quota 100m
  4  retention 1 year;
 
SQL> alter table haotest flashback archive haofbda2;

Table altered.

SQL> select TABLE_NAME,STATUS,ARCHIVE_TABLE_NAME from dba_flashback_archive_tables;

TABLE_NAME STATUS   ARCHIVE_TABLE_NAME
---------- -------- --------------------
HAOTEST    ENABLED  SYS_FBA_HIST_41909

SQL> update haotest set object_name='hao';

13093 rows updated.

SQL> commit;

Commit complete.

SQL> alter table haotest no flashback archive;

Table altered.

SQL>  select TABLE_NAME,STATUS,ARCHIVE_TABLE_NAME from dba_flashback_archive_tables;

TABLE_NAME STATUS   ARCHIVE_TABLE_NAME
---------- -------- --------------------
HAOTEST    DISABLED SYS_FBA_HIST_41909

SQL> desc SYS_FBA_HIST_41909
ERROR:
ORA-04043: object SYS_FBA_HIST_41909 does not exist

: ~/data/bdump > ps -ef|grep 6147
oracle    6147     1 57 03:15 ?        00:07:34 ora_fbda_hao2

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                               
 6147 oracle    25   0  955m  67m  62m R 76.2  5.5   7:48.60 oracle
 

: ~/data/bdump >  strace -i -c -p 6147
Process 6147 attached - interrupt to quit
Process 6147 detached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 38.94    0.111114          24      4679           getrusage
 35.75    0.102009          26      3953           gettimeofday
 20.91    0.059670          25      2367           times
  2.40    0.006848         129        53           semctl
  1.07    0.003044          28       108           lseek
  0.93    0.002645          24       108           read
------ ----------- ----------- --------- --------- ----------------
100.00    0.285330                 11268           total

經過strace,發現FBDA程式一直在getrusage和gettimeofday,沒有幹正事。

這時,我想,把FBDA程式幹掉應該會被重啟的,於是我就幹了。

: ~/data/bdump > kill -9 6147

果然在alert log裡:

2009-10-13 03:36:42.918000 +08:00
Restarting dead background process FBDA
FBDA started with pid=36, OS id=6240

但是非常不幸的是,當它被重啟之後,仍然佔用高CPU。

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                               
 6240 oracle    25   0  955m  30m  28m R 77.7  2.4   0:36.01 oracle

: ~/data/bdump > ps -ef|grep 6240
oracle    6240     1 76 03:36 ?        00:00:41 ora_fbda_hao2

這時,在alert log裡有trace檔案生成,開啟一看:

Flashback Archive: Error ORA-942 in SQL select ROWID from HAOZHU_USER.SYS_FBA_HIST_41909 where ROWNUM = 1
Flashback Archive: Error ORA-942 in SQL select ROWID from HAOZHU_USER.SYS_FBA_DDL_COLMAP_41909 where ROWNUM = 1
Flashback Archive: Error ORA-903 in SQL select ROWID from .SYS_FBA_TCRV_41909 where ROWNUM = 1

(00942, 00000, "table or view does not exist")

果然是跟沒有生成history table有關。

如果你想知道怎麼解決的,請往後接著看。

因為接下來就是另一個Bug。

2.2 Bug:DROP FLASHBACK ARCHIVE FAILS BY ORA-600[12811]
    Bug No: 6958073

在metalink上這篇bug出現在11.0.1.6上,同樣沒有任何解決辦法。

我之前那篇文章也提到過drop flashback archive會報600錯誤。

但現在在11.2.0.1上,會有什麼不同的地方麼?

SQL> drop flashback archive haofbda2;

Flashback archive dropped.
SQL> select FLASHBACK_ARCHIVE_NAME from dba_flashback_archive;

FLASHBACK_ARCHIVE_NA
--------------------
HAOFBDA2

SQL> drop flashback archive haofbda2;

Flashback archive dropped.

SQL> /

Flashback archive dropped.

SQL> /

Flashback archive dropped.

SQL> select FLASHBACK_ARCHIVE_NAME from dba_flashback_archive;

FLASHBACK_ARCHIVE_NA
--------------------
HAOFBDA2

果然,Oracle再次欺騙我說drop成功,但是在11.2上不會報出600錯誤來了。

但實際上FBDA仍然存在。

這時我看到tracked table跟FBDA仍然有關聯:

SQL> select TABLE_NAME,FLASHBACK_ARCHIVE_NAME,STATUS from dba_flashback_archive_tables;

TABLE_NAME FLASHBACK_ARCHIVE_NA STATUS
---------- -------------------- --------
HAOTEST    HAOFBDA2             DISABLED

於是我打算先drop purge這個已經被我disable FBDA的tracked table:

SQL> drop table HAOTEST purge;

Table dropped.

SQL> select TABLE_NAME,FLASHBACK_ARCHIVE_NAME,STATUS from dba_flashback_archive_tables;

no rows selected

大喜,果然這個表和FBDA的關聯被我取消了(其實沒有,後面會有闡述)。

但是仍然drop不掉FBDA:
SQL> drop flashback archive haofbda2;

Flashback archive dropped.

SQL> select FLASHBACK_ARCHIVE_NAME from dba_flashback_archive;

FLASHBACK_ARCHIVE_NA
--------------------
HAOFBDA2

到這裡,我終於被萬惡的FBDA給激怒了,於是開始玩火(反正在自己的虛擬機器上)。

我認為,這樣的bug很有可能是後臺程式沒有合理地修改內部表所造成的,肯定有什麼殘留的資訊。

首先,我找到所有%FBA%字樣的內部表:

: ~/data/arc > ora tablike FBA

OWNER                          TABLE_NAME                     TABLESPACE_NAME       INI_TRANS  FREELISTS NEXT_EXTENT PCT_INCREASE
------------------------------ ------------------------------ -------------------- ---------- ---------- ----------- ------------
SYS                            SYS_FBA_BARRIERSCN             SYSTEM                        1          1     1048576
SYS                            SYS_FBA_DL                     SYSTEM                        1          1     1048576
SYS                            SYS_FBA_FA                     SYSTEM                        1          1     1048576
SYS                            SYS_FBA_PARTITIONS             SYSTEM                        1          1     1048576
SYS                            SYS_FBA_TRACKEDTABLES          SYSTEM                        1          1     1048576
SYS                            SYS_FBA_TSFA                   SYSTEM                        1          1     1048576
SYS                            SYS_FBA_USERS                  SYSTEM                        1          1     1048576
SYS                            SYS_MFBA_NCHANGE                                             1          1
SYS                            SYS_MFBA_NROW                                                1          1
SYS                            SYS_MFBA_NTCRV                                               1          1
SYS                            SYS_MFBA_STAGE_RID                                           1          1
SYS                            SYS_MFBA_TRACKED_TXN                                         1          1

對每一個select一把,終於發現,我前面drop table haotest purge命令其實並沒有完全取消tracked table和FBDA的關聯。資訊還存在於FBDA內部表裡。

SQL> select * from SYS_FBA_TRACKEDTABLES;

      OBJ#        FA#    DROPSCN OBJNAME                        OWNERNAME                           FLAGS      SPARE
---------- ---------- ---------- ------------------------------ ------------------------------ ---------- ----------
     41909          1    3092606 HAOTEST                        HAOZHU_USER                             0
        -1         -1          0                                                                        1

那麼為什麼dba_flashback_archive_tables為顯示沒有任何資訊呢?

其實很簡單,我們檢視下dba_flashback_archive_tables的view的定義就知道了。

: ~/products/11r2/rdbms/admin > ora vdesc dba_flashback_archive_tables

VIEW                           TEXT
------------------------------ --------------------------------------------------------------------------------
SYS.DBA_FLASHBACK_ARCHIVE_TABL select o.NAME, u.NAME, f.FANAME, 'SYS_FBA_HIST_'||o.obj#,
ES                                  decode(t.DROPSCN, 0, 'ENABLED', 'DISABLED')
                               from OBJ$ o, USER$ u, SYS_FBA_FA f, SYS_FBA_TRACKEDTABLES t
                               where t.FA# = f.FA# and t.OBJ# = o.OBJ# and o.OWNER# = u.USER# and
                                 /* user has system privileges */
                                 exists (select null from v$enabledprivs where priv_number = -350)

原來dba_flashback_archive_tables會join OBJ#和SYS_FBA_TRACKEDTABLES,所以當我把haotest drop purge之後,OBJ#沒有了資訊,但是FBDA基表卻還有殘留的資訊。

於是一不做二不休,刪掉基表!

SQL> delete from SYS_FBA_TRACKEDTABLES;

2 rows deleted.

SQL> commit;

Commit complete.

再嘗試drop FBDA,依然不行。

SQL> drop flashback archive haofbda2;

Flashback archive dropped.

SQL> select FLASHBACK_ARCHIVE_NAME from dba_flashback_archive;

FLASHBACK_ARCHIVE_NA
--------------------
HAOFBDA2

於是怒了:

SQL> select * from SYS_FBA_FA;

FANAME
--------------------------------------------------------------------------------
       FA#  RETENTION  CREATESCN   PURGESCN      FLAGS     SPARE1     SPARE2
---------- ---------- ---------- ---------- ---------- ---------- ----------
OWNERNAME
------------------------------
HAOFBDA2
         1        365    3092163    3092163          4
HAOZHU_USER

SQL> delete from SYS_FBA_FA;

1 row deleted.

SQL> commit;

Commit complete.


SQL> select FLASHBACK_ARCHIVE_NAME from dba_flashback_archive;

no rows selected

但是即使如此,FBDA程式依然高CPU。

最後重啟資料庫,重新生成一個FBDA:

SQL> create flashback archive haofbda2
  2  tablespace fbdatbs
  3  quota 100m
  4  retention 1 year;

tablespace fbdatbs
           *
ERROR at line 2:
ORA-00001: unique constraint (SYS.SYS_C001424) violated

亂搞內部表的後遺症開始顯現。。。

於是順藤摸瓜,找到是哪張內部表有這個constraint:

SQL> select INDEX_NAME,TABLE_NAME from dba_constraints
  2  where CONSTRAINT_NAME='SYS_C001424';

INDEX_NAME                     TABLE_NAME
------------------------------ ------------------------------
SYS_C001424                    SYS_FBA_TSFA

SQL> select * from SYS_FBA_TSFA;

       FA#        TS#      QUOTA      FLAGS      SPARE
---------- ---------- ---------- ---------- ----------
         1          5        100        256

哦,原來FBDA和tablespace的關聯我還沒有刪掉。

SQL> delete from SYS_FBA_TSFA;

1 row deleted.

SQL> commit;

Commit complete.

刪掉這行之後,終於新建FBDA恢復正常!

SQL> create flashback archive haofbda2
  2  tablespace fbdatbs
  3  quota 100m
  4  retention 1 year;

Flashback archive created.

於是再enable一個FBDA看看有沒有其他後遺症:

SQL> alter table haotest flashback archive haofbda2;
alter table haotest flashback archive haofbda2
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [ktfa_lock_tt: fail], [0], [], [],
[], [], [], [], [], [], [], []

哈哈,我欣喜地發現了另一個後遺症,讓我來解決它!

我突然想起當初在delete SYS_FBA_TRACKEDTABLES的時候刪除了兩行,莫非其中obj#=-1的那行是無辜的?

還好我保留了screen,於是insert back!


SQL> insert into SYS_FBA_TRACKEDTABLES values
  2  (-1,-1,0,null,null,1,null);

1 row created.

SQL> commit;

Commit complete.

SQL> alter table haotest flashback archive haofbda2;

Table altered.

哈哈,又一個後遺症被我解決!

最後,我自己總結出解決以上兩個bug的非官方危險辦法:

delete from SYS_FBA_TRACKEDTABLES where obj#<>-1;

delete from SYS_FBA_TSFA;

delete from SYS_FBA_FA;

然後重啟資料庫。

這樣play with FBDA也會對自己瞭解FBDA是如何透過內部表產生關聯有了更深的理解。

當然,不推薦大家在生產資料庫玩。

 

    三. 11GR2的新東東們

在聊了這麼久FBDA的bug之後,聊點開心的吧。

3.1 新增的內部表們

: ~/products/11r2/rdbms/admin > ora tablike 41925

OWNER                          TABLE_NAME                     TABLESPACE_NAME       INI_TRANS  FREELISTS NEXT_EXTENT PCT_INCREASE
------------------------------ ------------------------------ -------------------- ---------- ---------- ----------- ------------
SYS                            SYS_FBA_DDL_COLMAP_41925       FBDATBS                       1                1048576
SYS                            SYS_FBA_HIST_41925
SYS                            SYS_FBA_TCRV_41925             FBDATBS                       1                1048576
SYS                            SYS_MFBA_NHIST_41925                                         1          1

我們可以看到,在我前一篇的文章中,只說了FBDA會產生兩個內部表。

但從這裡可以看出,FBDA有四個內部表了。

在這裡,我可以看到了FBDA NF PPT裡講的會支援更多DDL的苗頭了。

就是SYS_FBA_DDL_COLMAP_41925,它記錄了當前tracked table的column的名字和型別資訊。


SQL> select count(*) from SYS_FBA_DDL_COLMAP_41925;

  COUNT(*)
----------
        15

SQL> alter table haotest add id number;

Table altered.


SQL> select count(*) from SYS_FBA_DDL_COLMAP_41925;

  COUNT(*)
----------
        16

當然現在只支援add column,我想有了這個表,將來確是可能支援例如drop column、modify column的DDL。

至於SYS_MFBA_NHIST_41925,當我再次查詢時,他卻沒有了蹤影:

: ~/products/11r2/rdbms/admin > ora tablike 41925

OWNER                          TABLE_NAME                     TABLESPACE_NAME       INI_TRANS  FREELISTS NEXT_EXTENT PCT_INCREASE
------------------------------ ------------------------------ -------------------- ---------- ---------- ----------- ------------
SYS                            SYS_FBA_DDL_COLMAP_41925       FBDATBS                       1                1048576
SYS                            SYS_FBA_HIST_41925
SYS                            SYS_FBA_TCRV_41925             FBDATBS                       1                1048576

於是我懷疑他是一個temporary table,並且只有在幹活的時候才出現。

SQL> update haotest set object_name='hao2';

13093 rows updated.

SQL> select TABLE_NAME,TABLESPACE_NAME,COMPRESSION,READ_ONLY,TEMPORARY from dba_Tables where table_name='SYS_MFBA_NHIST_41925';

TABLE_NAME                     TABLESPACE_NAME                COMPRESS REA T
------------------------------ ------------------------------ -------- --- -
SYS_MFBA_NHIST_41925                                          DISABLED NO  Y

果然,他只在FBDA程式幹活的時候生成。具體做什麼的,估計是填充hist table時做的一箇中間臨時表。

 

3.2 DISASSOCIATE_FBA和REASSOCIATE_FBA

由於FBDA自己知道現在無法支援很多DDL語句,所以我想這是一個臨時的辦法。

他們就是:

SQL> desc dbms_flashback_archive
PROCEDURE DISASSOCIATE_FBA
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OWNER_NAME                     VARCHAR2                IN
 TABLE_NAME                     VARCHAR2                IN
PROCEDURE REASSOCIATE_FBA
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OWNER_NAME                     VARCHAR2                IN
 TABLE_NAME                     VARCHAR2                IN

當我們disassociate某個tracked table時,就可以對他做想要的DDL。然後再reassociate。

這讓我不禁想起了logical standby中的alter database guard none(all);

呵呵,用法很簡單,但是必須注意一點:

你的DDL不能更改column的名字或type。


SQL> exec dbms_flashback_archive.DISASSOCIATE_FBA(user,'HAOTEST');

PL/SQL procedure successfully completed.

SQL> alter table haotest modify id char;

Table altered.

SQL> exec dbms_flashback_archive.REASSOCIATE_FBA(user,'HAOTEST');
BEGIN dbms_flashback_archive.REASSOCIATE_FBA(user,'HAOTEST'); END;

*
ERROR at line 1:
ORA-55636: Flashback Data Archive enabled table "SYS"."HAOTEST" has different
definition from its history table
ORA-06512: at "SYS.DBMS_FLASHBACK_ARCHIVE", line 17
ORA-06512: at line 1

如果我打算手工同步hist table,不行:

SQL> alter table SYS_FBA_HIST_41925 modify id char;
alter table SYS_FBA_HIST_41925 modify id char
*
ERROR at line 1:
ORA-55622: DML, ALTER and CREATE UNIQUE INDEX operations are not allowed on
table "SYS"."SYS_FBA_HIST_41925"

我只得將id column改回來。但這種方法給了我們truncate table等不影響column結構的DDL的機會,這些DDL在原來的版本中是無法執行的。

這算是FBDA的一大進步!

SQL>  exec dbms_flashback_archive.DISASSOCIATE_FBA(user,'HAOTEST');

PL/SQL procedure successfully completed.

SQL> alter table haotest modify id number;

Table altered.

SQL> truncate table haotest;

Table truncated.

SQL>  exec dbms_flashback_archive.REASSOCIATE_FBA(user,'HAOTEST');

PL/SQL procedure successfully completed.

 

好了,寫了這麼多,其目的就是讓大家更好的理解FBDA和使用FBDA,雖然現在FBDA仍然有很多我們無法容忍的bug和缺點,但相信不久之後的11.2會有更大的提高和更完善的修復。

 

   --Hao 2009.10.12 21:00pm 寫於office

 

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15415488/viewspace-616363/,如需轉載,請註明出處,否則將追究法律責任。

相關文章