轉載: https://blog.csdn.net/chensrao/article/details/6200338
一、增量數據採集概述
數據採集通常是指ETL過程中Extract-數據抽取部分。除了ETL外在不同應用系統之間通常也需要傳遞數據,在某些環境條件限制下不能將數據從一個系統直接移到另一個系統,只能藉助文本來作爲中間媒介傳遞數據,且文本的生成有時間窗口的限制,所以對數據採集即數據抽取的性能有一定的要求。對增加數據的採集的方法常用的有以下幾種:
1. 時間戳(Timestamps on rows)
2. 版本號(Version Numbers on rows)
3. 狀態指示(Status indicators on rows)
4. 時間戳、版本號、狀態指示混合使用(Time/Version/Status on rows)
5. 觸發器 (Triggers on tables)
6. 表差異(Table differencing)
7. 數據庫的日誌掃描(Log scanners on databases)
對於增量數據採集情況在Oracle中推出了兩種主要方案,一種是我們熟悉的物化視圖(materialized view),另一種就是本文將要介紹的CDC組件(Change Data Capture 改變數據捕獲)。
CDC 特性是在Oracle9i數據庫中引入的。CDC能夠幫助你識別從上次提取之後發生變化的數據。利用CDC,在對源表進行INSERT、UPDATE或 DELETE等操作的同時就可以提取數據,並且變化的數據被保存在數據庫的變化表中。這樣就可以捕獲發生變化的數據,然後利用數據庫視圖以一種可控的方式提供給目標系統。
二、CDC的發佈訂閱模型
CDC體系結構基於發佈者/訂閱者模型。發佈者捕捉變化數據並提供給訂閱者。訂閱者使用從發佈者那裏獲得的變化數據。通常,CDC系統擁有一個發佈者和多個訂閱者。發佈者首先需要識別捕獲變化數據所需的源表。然後,它捕捉變化的數據並將其保存在特別創建的變化表中。它還使訂閱者能夠控制對變化數據的訪問。訂閱者需要清楚自己感興趣的是哪些變化數據。一個訂閱者可能不會對發佈者發佈的所有數據都感興趣。 訂閱者需要創建一個訂閱者視圖來訪問經發布者授權可以訪問的變化數據。
CDC有幾個重要的基本概念需要先明確一下:
l 源表(Source Table),業務數據庫的需要捕獲數據的源表
l 變化表(Change Table) ,保存從源表捕獲的變化數據(包括各種DML產生的數據)
l 變化集(Change Set),是保證事務一致性的數據集合。一個變化集對應多個變化表
l 訂閱視圖(Subscription View),提供給讀取變化表數據的視圖
l 訂閱窗口(Subscription Window) ,定義了查看變化數據的時間範圍.就象一個觀察變化數據的滑動窗口。變化數據處理完成後,可以對清除訂閱窗口。
三、CDC的同步與異步模式
l 同步模式,實時的捕獲變化數據並存儲到變化表中,發佈者與訂閱都位於同一數據庫中,同步模式實際使用trigger的形式來捕捉變化數據。下圖說明了同步模式的基本架構。
l 異步模式,以Oracle流複製技術爲基礎,從redo log中讀取日誌記錄來捕捉變化數據。異步模式有三種:
1. Asynchronous HotLog
2. Asynchronous Distributed HotLog
3. Asynchronous AutoLog Mode
3.1 Asynchronous Autolog Online Change Data Capture
3.2 Asynchronous AutoLog Archive Change Data Capture
四、CDC相關的數據庫對象 (Package)
l 包(Package)
n DBMS_CDC_PUBLISH, 用於定義發佈操作
n DBMS_CDC_SUBSCRIBE,用於定義訂閱操作
l 角色
n EXECUTE_CATALOG_ROLE
n SELECT_CATALOG_ROLE
n CREATE TABLE and CREATE SESSION privileges
n EXECUTE on the DBMS_CDC_PUBLISH package
l 視圖
n ALL_SOURCE_TABLES 源表
n ALL_PUBLISHED_COLUMNS 發佈的表列
n All_Subscribed_Columns 訂閱的表列
n All_Subscriptions 所有訂閱
n All_Subscribed_Tables 已經訂閱的表
五、CDC的實施步驟
同步模式以trigger形式來捕捉,這種實行沒有自身來使用trigger來捕捉來的靈活,且其對性能的影響比從日誌捕捉變化數據的性能影響大,所以本文以異步捕捉中的異步Hotlog來講解CDC的具體實施步驟.
1. 準備數據和用戶
SQL>show user scott SQL>create table t1 ( a_num number , b_varchar varchar2(10),c_char char(10));#測試表 SQL>conn / as sysdba SQL>create user cdcpub identified by cdcpub; #發佈用戶(publisher) SQL>create user subscriber1 identified by subscriber1;#訂閱者(subscriber) |
2. 調整數據庫參數(需根據實際情況修改)
compatible = 10.2.0 java_pool_size = 50000000 job_queue_processes = 2 parallel_max_servers = + 5 processes = + 7 sessions = + 2 streams_pool_size = + 21 MB undo_retention = 3600 |
3. 修改數據庫日誌模式
#數據庫默認是在archivelog模式 SQL>show user USER is “sys” SQL>ALTER DATABASE FORCE LOGGING; #此步驟是可選但建議執行; SQL>ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;#此步驟需執行; SQL>ALTER TABLE scott.t1 ADD SUPPLEMENTAL LOG GROUP log_group_t1 (a_num,b_varchar,c_char) ALWAYS; #若要捕捉t1表中所有列,可用下列語句代替上述alter table語句: #ALTER TABLE scott.t1 ADD SUPPLEMENTAL LOG DATA (ALL) #COLUMNS; |
4. 授權
ALTER USER cdcpub QUOTA UNLIMITED ON SYSTEM QUOTA UNLIMITED ON SYSAUX; GRANT CREATE SESSION TO cdcpub; GRANT CREATE TABLE TO cdcpub; GRANT CREATE TABLESPACE TO cdcpub; GRANT UNLIMITED TABLESPACE TO cdcpub; GRANT SELECT_CATALOG_ROLE TO cdcpub; GRANT EXECUTE_CATALOG_ROLE TO cdcpub; GRANT CREATE SEQUENCE TO cdcpub; GRANT DBA TO cdcpub; GRANT EXECUTE on DBMS_CDC_PUBLISH TO cdcpub; EXECUTE DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE(GRANTEE => 'cdcpub'); |
5. 準備源表(Source Table)
SQL>show user USER is “SYS” SQL> BEGIN DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(TABLE_NAME => 'scott.t1'); END; / |
6. 創建變更集(Change Set)
SQL>show user USER is “cdcpub” SQL> BEGIN DBMS_CDC_PUBLISH.CREATE_CHANGE_SET( change_set_name => 'cdc_test_cs', description => 'Change set for scott.t info', change_source_name => 'HOTLOG_SOURCE', stop_on_ddl => 'y' ); END; / |
7. 創建變更表(Change Table)
SQL>show user USER is “cdcpub” SQL> BEGIN DBMS_CDC_PUBLISH.CREATE_CHANGE_TABLE( owner => 'cdcpub', change_table_name => 't1_ct', change_set_name => 'cdc_test_cs', source_schema => 'scott', source_table => 't1', column_type_list =>'a_num number,b_varchar varchar2(10),c_char char(10)', capture_values => 'both', rs_id => 'y', row_id => 'n', user_id => 'n', timestamp => 'n', object_id => 'n', source_colmap => 'n', target_colmap => 'y', options_string => ''); END; / |
8. 激活變更集(Change Set)
SQL>show user USER is “cdcpub” SQL> BEGIN DBMS_CDC_PUBLISH.ALTER_CHANGE_SET( change_set_name => 'cdc_test_cs', enable_capture => 'y'); END; / |
9. 授權給訂閱者
SQL>show user USER is “cdcpub” SQL> GRANT SELECT ON cdcpub.t1_ct TO subscriber1; SQL>show user USER is “SYS” SQL>GRANT CREATE TABLE TO subscriber1; SQL>GRANT CREATE SESSION TO subscriber1; SQL>GRANT CREATE VIEW TO subscriber1; SQL>GRANT UNLIMITED TABLESPACE TO subscriber1; |
10. 訂閱變更數據
i. 創建訂閱集(subscription)
SQL>show user USER is “subscriber1” SQL> BEGIN DBMS_CDC_SUBSCRIBE.CREATE_SUBSCRIPTION( change_set_name => 'cdc_test_cs', description => 'Change data for t1', subscription_name => 't1_sub'); END; / |
ii. 訂閱源表及源表中的相關字段
SQL>show user USER is “subscriber1” SQL> BEGIN DBMS_CDC_SUBSCRIBE.SUBSCRIBE( subscription_name => 't1_sub', source_schema => 'scott', source_table => 't1', column_list => 'a_num,b_varchar,c_char', subscriber_view => 't1_view'); END; / |
iii. 激活訂閱
SQL>show user USER is “subscriber1” SQL> BEGIN DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION( subscription_name => 't1_sub'); END; / |
iv. 擴展訂閱窗口
SQL>show user USER is “subscriber1” SQL> BEGIN DBMS_CDC_SUBSCRIBE.EXTEND_WINDOW( subscription_name => 't1_sub'); END; / #extend_window功能說明:此過程是設置訂閱窗口的高位邊界,只要設置 #了新數據才能看到新數據; |
v. 查看訂閱視圖內容
SQL>show user USER is “subscriber1” SQL>select * from t1_view; #因scott.t1表中無數據變更所以當前視圖無數據 no rows selected SQL>conn scott/tiger SQL> insert into t1 values(2,'cdc_test1','cdc'); SQL>commit; SQL>conn subscriber1/subscriber1 SQL> BEGIN DBMS_CDC_SUBSCRIBE.EXTEND_WINDOW( subscription_name => 't1_sub'); END; / SQL>select OPERATION$,a_num,b_varchar,c_char from t1_view OP A_NUM B_VARCHAR C_CHAR -- ---------- ---------- ---------- I 2 cdc_test1 cdc |
vi. 清除變更集數據
如果當前變更數據不在需要使用,可以清除爲後續生成的數據騰出空間;
BEGIN DBMS_CDC_SUBSCRIBE.PURGE_WINDOW( subscription_name => 'SALES_SUB'); END; / |
vii. 刪除訂閱:
如果當前訂閱不需要再使用可以刪除;
BEGIN DBMS_CDC_SUBSCRIBE.DROP_SUBSCRIPTION( subscription_name => 't1_sub'); END; / |
參考:
Oracle® Database Data Warehousing Guide 10g Release 2 (10.2) B14223-02 Chapter 16