Oracle中的補充日誌(supplemental log)

在配置DG的時候,有涉及到補充日誌的知識,故做以整理。

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


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

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

如:update scott.emp set sal=12000 where empno=7369 ;

爲了支持實例恢復和介質恢復,其重做記錄只需要記載sal字段的值爲12000即可,在常規的重做記錄中完全不會出現empno爲7369的信息

Insert、delete、update的常規重做記錄具體記載何種信息是以保證實例恢復與介質恢復能夠正常進行爲標準的,不相關的信息不會記錄在重做日誌中。正是因爲有撤銷數據塊的變更矢量,所以保證實例恢復與介質恢復也簡介地保證了回滾操作可以被執行。

如果啓用了補充日誌,數據塊的變更矢量的記載可以變爲; sal字段的值爲12000,並且再額外的記錄該行被修改之前第一個字段empno的值是7369以及sal爲800(修改之前的值),更多的信息意味着update命令被等價還原的可能性提高了,數據的恢復性提高

補充日誌主要就是爲update服務,補充的目的就是要高度還原真實的update命令。


補充日誌可以在數據庫級別和表級別上啓用

supplemental log可以在數據庫級別啓動,在數據庫級別啓動minimal logging會記錄操作的足夠信息,通常邏輯standby數據庫創建minimal logging已經足夠使用。數據庫supplemental log補充日誌還能針對所有字段、主鍵字段、唯一字段和外鍵字段創建。也可以設置表級別設置supplemental log,稱爲identification key logging,不同類型的supplemental log會產生不同大小的日誌記錄。

針對邏輯standby數據庫記錄的日誌信息有以下規則:

如果一個表有主鍵被定義,那麼主鍵被記錄作爲update語句的一部分來標識修改的行

如果主鍵不存在,最短的非空約束、唯一索引被記錄作爲update語句的一部分來標識修改的行在主鍵和非空約束/索引都沒有的情況下,所有的列被記錄,作爲update語句的一部分來標識修改的行,也就是除了long,lob,longg raw,對象類型和集合類型的字段,所有字段都將被記錄一個函數索引,即使它被定義爲唯一的,也不能用於唯一標識修改的行,只要修改的行能被唯一標識,邏輯standby數據庫支持函數索引表的同步

推薦主數據庫儘可能給表添加主鍵或者非空唯一索引,確保sql apply能有效應用redo數據來更新邏輯standby數據庫。

查找數據庫中沒有唯一邏輯標識的表

select owner, table_name
  from dba_logstdby_not_unique
 where (owner, table_name) not in
       (select distinct owner, table_name from dba_logstdby_unsupported)
   and bad_column = 'Y';

添加禁用主鍵rely的約束

如果能確保應用在表中的行爲是唯一的,在表上創建禁用主鍵rely約束,這能避免維護

主數據庫主鍵的開銷在主數據庫表上使用alter table語句的relay disable子句創建禁用主鍵rely約束,表test有兩列ID、name,以下sql在test表創建禁用rely約束

alter table test add primary key (id,name) rely disable ;

當明確指定了rely約束,系統將嘉定行能通過指定字段標識唯一性

爲了提高sql apply的性能,在表的字段上添加唯一的約束/索引,確保邏輯standby數據庫維護的表都能唯一標識行,如果沒添加唯一的約束/索引,當通過sql apply在表上執行update或者delete語句期間會全表掃描,會降低性能。


查看當前數據庫中補充日誌狀態:

SQL> select * from v$version ;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE	11.2.0.3.0	Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

SQL> 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;  2    3    4    5    6  

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

可以看到,補充日誌的類型有:最小補充日誌、標識關鍵字段補充日誌兩大類

1.最小補充日誌

最小補充日誌是最基本的一種數據庫級補充日誌,

啓用最小補充日誌

SQL> alter database add supplemental log data ;

Database altered.

SQL> select supplemental_log_data_min min from v$database ;

MIN
--------
YES

關閉最小補充日誌

SQL> alter database drop supplemental log data ;

Database altered.

SQL> select supplemental_log_data_min min from v$database ;

MIN
--------
NO

需要注意的是,凡是啓用或者關閉數據庫級補充日誌(包括最小補充日誌和另外幾種日誌)都會導致共享池中所有SQL命令遊標非法,也就是短期之內應解析會顯著上升。

2.標識關鍵字段補充日誌

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

2.1主鍵補充日誌

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

啓用主鍵補充日誌:

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

Database altered.

SQL> select supplemental_log_data_pk as pk from v$database ;

PK
---
YES

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

同樣在沒有關閉標識關鍵字段補充日誌的時候,不能先關閉最小補充日誌

SQL> 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;  2    3    4    5    6  

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

2.2唯一索引補充日誌

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

如:

SQL> create unique index name_idx on hr.employees(first_name,last_name);

Index created.

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

Database altered.

SQL> select supplemental_log_data_ui ui from v$database ;

UI
---
YES

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

2.3外鍵補充日誌

外鍵補充日誌和唯一索引補充日誌一樣同爲有條件式的,只有當外鍵字段被update命令

修改時,其修改前的舊值纔會被記錄。所以這種補充日誌完全是爲複合字段外鍵服務的

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

Database altered.

SQL> 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;  2    3    4    5    6  

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

2.4全體字段補充日誌

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

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

Database altered.

SQL> 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;  2    3    4    5    6  

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

數據庫級的補充日誌,共同點是啓用和關閉導致所有SQL遊標非法

無論需要啓用哪一種標識關鍵字段補充日誌,都需要啓用最小補充日誌,4種標識關鍵字段的效果可以累加,不衝突。

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

Database altered.

SQL> 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;  2    3    4    5    6  

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

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

Database altered.

SQL> 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;  2    3    4    5    6  

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

表級補充日誌

只是針對某個表,沒有必要在整個數據庫範圍啓用補充日誌功能,在啓用表級補充日誌之前,應該先啓用數據庫級最小補充日誌

表級補充日誌分爲主鍵、唯一索引、外鍵、全字段和自定義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命令,由於額外記錄了字段的舊值,也能將其看成一種特殊的備份。

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