oracle的補全日誌--Supplemental Logging

補充日誌不是獨立的一種日誌,是對重做記錄中變更矢量的補充信息,增加了變更矢量記載的記錄量,Oracle數據庫某些功能要求啓用補充日誌才能正常地或更好的工作,如logminer、DG、閃回事務查詢、閃回事務。

Oracle中insert、delete命令在默認情況下產生的重做記錄足以表明被修改的行的每個字段在被修改前後的值是什麼,insert,變更前行不存在,產生的重做記錄會記載新行的每個字段的值,delete,變更後不存在,但是由於重做記錄也要負責產生撤銷數據塊的變更,所以行被刪除之前的各字段的值也記錄在撤銷數據塊的變更矢量中,也就是insert和delete命令的重做記錄中,能找到整行的所有信息。

但是update不同於insert和delete一定會涉及一行的所有字段,常常只是更改一個或幾個字段,處於對性能的考慮,Oracle沒必要把修改的字段的值也保存在變更矢量中,事實上是在撤銷塊的變更矢量中只記載被修改的字段的更改前的值,而在數據塊的變更矢量中則記載了被修改的字段的新值,同一行中其他沒有被修改的字段,不會記載其修改前的值,因爲沒有被修改。

Oracle日誌(redo log)一般用於實例恢復和介質恢復,但是如果需要靠日誌還原完整的DML操作信息(比如Logmnr、Streams和這裏的Goldengate),默認記錄的日誌量還不夠。比如一個UPDATE的操作,默認redo只記錄了rowid以及被修改的字段信息,但這裏GoldenGate還原這個事務,因爲不是根據rowid而是SQL層面根據唯一鍵值來定位記錄,所以還需要將主鍵或者其他字段的信息附加到日誌中去。要往日誌中增加這些額外字段信息的操作,就是開啓補全日誌,即Add Supplemental Logging。打開補全日誌,會使數據庫的日誌量增加,所以只打開需要的級別和對象即可。

Oracle補全日誌可以在數據庫級別設置,也可以在表級別設置。在數據庫級別中,補全日誌按補全的信息量,對應好幾個級別:

(1)最小附加日誌(Minimal supplemental logging):是開啓logmnr的最低日誌要求,提供了行鏈接(chained rows)和多種數據存儲(比如聚簇表、索引組織表)的信息。在Oracle 9.2之後的版本中,默認都不開啓。

(2)主鍵補全(Primary key supplemental logging):在日誌中補全所有主鍵列。如果表中無主鍵,則補全一個非空唯一索引列;如果非空唯一索引鍵也沒,那麼會補全除了LOB和LONG類型字段以外的所有列,這時就和下面的所有補全一樣了。

(3)唯一鍵補全(Unique key supplemental logging):當唯一鍵列或位圖索引列被修改時,在日誌中補全所有唯一鍵列或位圖索引列。打開唯一鍵補全也會同時打開主鍵補全。注意這個級別是需要條件觸發的。

(4)外鍵補全(Foreign Key supplemental logging):當外鍵列被修改時,將在日誌中補全所有外鍵列。這個級別也是需要條件觸發的。

(5)所有補全(All supplemental logging):在日誌中補全所有字段(排除LOB和LONG類型)。

數據庫級別中的5個類型中,除了最小附加日誌級別,都可以在表級進行設置。除此之外,表級還可以明確指定需要補全的列。

Oracle表級補全日誌需要在最小補全日誌打開的情況下才起作用,即若一個數據庫沒有開最小補全日誌或之前drop supplemental log data操作則即便指定了表級補全日誌,實際在重做日誌輸出的過程中描述的記錄仍只記錄rowid和相關列值。而要關閉最小補全日誌,也必須首先關閉數據庫級別的其他補全級別後,才能關閉。

打開數據庫級別的最小補全日誌
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;  

查看是否開啓
select supplemental_log_data_min min from v$database ;

關閉最小補全日誌
alter database drop supplemental log data ;

標識關鍵字段補充日誌有四種:主鍵、唯一索引、外鍵、全體字段補充日誌

(1)主鍵補充日誌

主鍵補充日誌的作用是在update命令的重做記錄中添加被修改行的主鍵字段的舊值,這是無條件式的補充日誌,所謂無條件即無論主鍵字段本身是否被update命令修改,其舊值都會被記錄。但是,不能保證每張表一定有主鍵。如果存在沒有主鍵的表,則主鍵字段由長度最小的非空唯一索引字段代替。如果表結構中一個非空索引字段都沒有,那麼oracle將被修改行的所有字段(除了lob和long類型)的舊值都記錄下來,這將導致重做記錄的數據量暴漲,所以如果要啓用主鍵補充日誌,又爲了維護lgwr和重做日誌,每張表最好具有主鍵或至少一個非空唯一字段。

啓用主鍵補充日誌:
alter database add supplemental log data (primary key) columns ;
 
查看是否開啓
select supplemental_log_data_pk as pk from v$database ;

標識關鍵字段補充日誌(包括主鍵補充日誌)必須建立在最小補充日誌的基礎上,當其被啓用時,若最小補充日誌尚未啓用,則oracle會隱式開啓最小補充日誌 狀態爲IMPLICIT,同樣在沒有關閉標識關鍵字段補充日誌的時候,不能先關閉最小補充日誌。

select SUPPLEMENTAL_LOG_DATA_MIN min,
       SUPPLEMENTAL_LOG_DATA_PK  pk,
       SUPPLEMENTAL_LOG_DATA_UI  ui,
       SUPPLEMENTAL_LOG_DATA_FK  fk,
       SUPPLEMENTAL_LOG_DATA_ALL "all"
  from v$database;

SQL> select SUPPLEMENTAL_LOG_DATA_MIN min,
  2         SUPPLEMENTAL_LOG_DATA_PK  pk,
  3         SUPPLEMENTAL_LOG_DATA_UI  ui,
  4         SUPPLEMENTAL_LOG_DATA_FK  fk,
  5         SUPPLEMENTAL_LOG_DATA_ALL "all"
  6    from v$database;

MIN	 PK  UI  FK  all
-------- --- --- --- ---
YES	 NO  NO  NO  NO

SQL> alter database drop supplemental log data ;

Database altered.

SQL> select SUPPLEMENTAL_LOG_DATA_MIN min from v$database;

MIN
--------
NO

SQL> alter database add supplemental log data (primary key) columns ;

Database altered.

SQL> select SUPPLEMENTAL_LOG_DATA_MIN min,
  2         SUPPLEMENTAL_LOG_DATA_PK  pk,
  3         SUPPLEMENTAL_LOG_DATA_UI  ui,
  4         SUPPLEMENTAL_LOG_DATA_FK  fk,
  5         SUPPLEMENTAL_LOG_DATA_ALL "all"
  6    from v$database;

MIN	 PK  UI  FK  all
-------- --- --- --- ---
IMPLICIT YES NO  NO  NO


SQL> alter database drop supplemental log data ;
alter database drop supplemental log data
*
ERROR at line 1:
ORA-32589: unable to drop minimal supplemental logging

--刪除主鍵補充日誌
ALTER DATABASE DROP SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;  


SQL> ALTER DATABASE DROP SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;  

Database altered.

SQL> alter database drop supplemental log data ;

Database altered.

SQL> select SUPPLEMENTAL_LOG_DATA_MIN min,
  2         SUPPLEMENTAL_LOG_DATA_PK  pk,
  3         SUPPLEMENTAL_LOG_DATA_UI  ui,
  4         SUPPLEMENTAL_LOG_DATA_FK  fk,
  5         SUPPLEMENTAL_LOG_DATA_ALL "all"
  6    from v$database;

MIN	 PK  UI  FK  all
-------- --- --- --- ---
NO	 NO  NO  NO  NO

(2)唯一索引補充日誌

只有當唯一字段被update時,纔會記錄該字段被修改前的值,因爲唯一鍵索引是能夠建立在多個字段上的。

打開唯一索引補充日誌
alter database add supplemental log data (unique) columns ;

查看是否打開
select supplemental_log_data_ui ui from v$database ;

刪除唯一索引補全日誌
alter database drop supplemental log data (unique) columns ;

如:
create unique index name_idx on hr.employees(first_name,last_name);

alter database add supplemental log data (unique) columns ;
 
SQL> select supplemental_log_data_ui ui from v$database ;
 
UI
---
YES

update 命令現在更新first_name,常規日誌會只記載first_name字段的舊值,而唯一鍵索引將會記錄first_name和last_name,所以這種補充日誌完全可以說是爲複合字段唯一索引服務的。

(3)外鍵補充日誌

外鍵補充日誌和唯一索引補充日誌一樣同爲有條件式的,只有當外鍵字段被update命令修改時,其修改前的舊值纔會被記錄。所以這種補充日誌完全是爲複合字段外鍵服務的。

打開外鍵補全日誌
alter database add supplemental log data (foreign key) columns ;

查看是否打開
select supplemental_log_data_fk as fk from v$database ;

刪除外鍵補全日誌
alter database drop supplemental log data (foreign key) columns ;

(4)全體字段補充日誌

全體字段補充日誌和主鍵補充日誌一樣爲無條件式的,無論哪個字段被update命令修改,所有字段(除了lob,long類型)的舊值都將被記錄,其效果相當於啓用了主鍵補充日誌的前提下既沒有主鍵也沒有非空唯一索引字段的情況,這樣幾乎所有的表數據都搬到了重做日誌中,不但存在當前的,歷史數據也沒有丟下。對恢復操作來說比較好,但是對於lgwr和磁盤空間就不是太好,一般很少啓用這樣的日誌。

打開all補全日誌
alter database add supplemental log data (all) columns; 

查看是否打開
select supplemental_log_data_all as all from v$database ;

刪除all補全日誌
alter database drop supplemental log data (all) columns; 

數據庫級的補充日誌,共同點是啓用和關閉導致所有SQL遊標非法。無論需要啓用哪一種標識關鍵字段補充日誌,都需要啓用最小補充日誌,4種標識關鍵字段的效果可以累加,不衝突。

alter database add supplemental log data (primary key,unique,foreign key,all) columns ;

alter database drop supplemental log data (primary key,unique,foreign key,all) columns ;

表級補充日誌

只是針對某個表,沒有必要在整個數據庫範圍啓用補充日誌功能,在啓用表級補充日誌之前,應該先啓用數據庫級最小補充日誌。表級補充日誌分爲主鍵、唯一索引、外鍵、全字段和自定義5種類型,前四種和數據庫級對應的類型特點一致,只是在特定的表上啓用。

alter table scott.emp add supplemental log data (primary key) columns ;

alter table scott.emp add supplemental log data (unique) columns ;

alter table scott.emp add supplemental log data (foreign key) columns ;

alter table scott.emp add supplemental log data (all) columns ;

自定義字段是表級補充日誌特有的功能,用戶可以任意指定哪些字段的舊值需要被補充記錄。

alter table hr.employees add supplemental log group emp_info (first_name,last_name,email) ;

以上將first_name,last_name,email字段指派爲一個名爲empinfo的日誌組,意思就是隻要update命令修改了這3個字段中的任意一個,重做記錄必須記載全部3個字段的舊值這稱爲有條件式的,無條件式的要加關鍵字always

alter table hr.employees add supplemental log group emp_info (first_name,last_name,email) always ;


表級補充日誌的情況可以查詢dba_log_groups和dba_log_grup_columns

select g.log_group_name name,
       g.owner || '.' || g.table_name table_name,
       g.always,
       g.generated,
       c.column_name
  from dba_log_groups g, dba_log_group_columns c
 where g.log_group_name = c.log_group_name(+)
   and g.table_name = c.table_name(+)
   and g.table_name = 'EMPLOYEES'
   and g.owner = 'HR'
 order by 1, 2, 3, 4;

特定表上的表級補充日誌的啓用與關閉會導致所有引用該表的SQL遊標非法,會引起一段時間的硬分析增加。

補充日誌主要爲update服務,額外記錄指定字段的舊值,使得有能力分析重做日誌的工具可以高度還原update命令,由於額外記錄了字段的舊值,也能將其看成一種特殊的備份。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章