一步一步學Streams(7) 第一部分 基礎之應用程式(中)
4. 應用DDL修改
4.1. APPLY 程式忽略的DDL語句
APPLY 應用不支援下列型別的DDL語句:
- ALTER MATERIALIZED VIEW
- ALTER MATERIALIZED VIEW LOG
- CREATE DATABASE LINK
- CREATE SCHEMA AUTHORIZATION
- CREATE MATERIALIZED VIEW
- CREATE MATERIALIZED VIEW LOG
- DROP DATABASE LINK
- DROP MATERIALIZED VIEW
- DROP MATERIALIZED VIEW LOG
- RENAME
如果apply程式在應用DDL LCR時發現不支援的操作,會自動忽略該LCR並記錄一條資訊到apply程式的trace檔案。
注意:
Alter objectType objectName rename 語句是能夠被apply應用支援的,比如alter table rename之類的。Snapshot是materialized view的同義詞,因此snapshot相關的語句也不會被apply應用支援。4.2. Streams 複製環境中的資料結構
資料結構不僅包含資料檔案、表空間、回滾段之類物理結構,還有比如表結構等等邏輯結構。捕獲的DDL要在目標端完全應用,要麼確保源和目標端的結構一致,要麼在源端執行sql語句時不要包含目標端沒有的物件。
比如說,一項對錶做修改的DDL要想在目標端成功應用,需要考慮下列諸項因素:
- Create table 的儲存引數相同
- 如果指定了回滾段,表空間等項,則該表空間/回滾段必須確實存在於目標端。
- 如果指定了分割槽資訊,則分割槽在目標端也必須有效。
注意DDL應用時,執行ddl的shcema必須已經存在於目標端資料庫。
4.3. 系統產生的物件名稱
應儘可能避免系統產生的物件名稱。因為源端捕獲的實際還是ddl語句,這樣在目標端應用後,如果是由系統自動生成名稱,則源端和目標端名稱有可能會不一致,這就有可能導致後續應用的一些問題。
比如說源端執行這樣的語句:
CREATE TABLE tbl (n1 NUMBER NOT NULL);
則系統會自動建立一個not null的約束,假設源端名稱為定義為sys_000115,目標端應用create table語句時,可能為該約束建立一個非sys_000115的名字(畢竟源端與目標端並非一模一樣),當你再執行刪除該約束時:
Alter table tbl drop constraint sys_000115;
源端可以正確執行,但目標端在應用該語句時就有可能報找不到sys_000115物件的錯誤,正確的方式,應該是在建立時指定名稱,比如:
Create table tbl (n1 number constraint ck_tbl_nlnull not null);
4.4. CREATE TABLE AS SELECT 語句的執行
應用create table as select語句時,apply程式執行如下兩個步驟:
- 目標端執行CREATE TABLE AS SELECT語句,不過只建立表並不生成資料。如果失敗則apply程式返回錯誤資訊,否則繼續執行下一步。
- 插入資料。注意這一步實際插入的記錄可能會受到capture/propagation/apply程式的自定義規則影響,實際插入記錄有可能與源端不同。
5. 觸發器屬性
你可以通過DBMS_DDL.SET_TRIGGER_FIRING_PROPERTY過程控制DML/DDL觸發器的觸發,該過程控制觸發器是否只觸發一次。
如果該過程的fire once引數設定為true(預設情況下該引數即是true,你可以通過DBMS_DLL.IS_TRIGGER_FIRE_ONCE函式檢查觸發器的觸發屬性設定),下列情況不會觸發觸發器。
- 相關更新由apply程式產生。
- 執行DBMS_APPLY_ADM.EXECUTE_ERROR/EXECUTE_ALL_ERRORS過程產生的修改。
舉個例子,Schema:hr中建立觸發器update_job_history,當employees表中job_id或department_id被更新時自動插入記錄到job_history表,當前streams複製環境如下:
- dbs1.net 源端capture程式同時捕獲兩張表的修改
- Propagation 傳播修改到目標端dbs2.net
- Apply 程式在目標端應用修改
- Update_job_history 觸發器存在於源端和目標端。
如果目標端dbs2.net中update_job_history觸發屬性不是fire once的話,實際操作如下:
- 源端dbs1.net中employees.job_id被修改
- Update_job_history 被觸發,新記錄插入到job_history表
- 源端的capture程式同時捕獲到employees和job_history的修改
- 修改被傳播到目標端dbs2.net
- 目標端應用這兩表的修改
- 目標端應用employees表修改時update_job_history觸發器再次被觸發,又有記錄被插入job_history表
由上可知,job_history中實際是產生了重複記錄了的,多數情況下我們可能是不希望產生這種狀況,如果我們設定update_job_history的觸發屬性為fire once(或者在建立觸發器時指定on schema子句),則dbs2.net端就不會再被觸發了。
6. APPLY 程式支援的資料型別
下列資料型別可被apply程式支援:
- VARCHAR2
- NVARCHAR2
- NUMBER
- LONG
- DATE
- BINARY_FLOAT
- BINARY_DOUBLE
- TIMESTAMP
- TIMESTAMP WITH TIME ZONE
- TIMESTAMP WITH LOCAL TIME ZONE
- INTERVAL YEAR TO MONTH
- INTERVAL DAY TO SECOND
- RAW
- LONG RAW
- CHAR
- NCHAR
- CLOB
- NCLOB
- BLOB
- UROWID
不支援的型別有:BFILE, ROWID, and user-defined type (including object types, REFs, varrays, nested tables, and Oracle-supplied types)等。另外,apply程式不支援transparent data加密過的資料,不管加密資料是什麼型別。
7. APPLY 程式與受限連線
如果以startup restrict模式啟動資料庫的話,apply程式就不會被啟動。如果是以alter system enable restricted session語句將資料庫置為restrict模式的話,對於當前正在執行的apply程式不會有影響,但不會再有新的apply程式啟動,直到disable restricte。
8. APPLY 程式與RAC
RAC 環境下apply程式是與例項繫結的,即各例項管理各自的apply程式,如果某個apply程式因某種原因不可用的話,佇列ownership自動轉換至叢集中其它例項。同時apply程式也會隨著佇列轉移至相應例項。另外,啟用狀態的apply程式所在例項不可用的話,apply程式會自動在新例項上啟動,而未啟用狀態的apply程式所在例項不可用的話,apply程式在新例項中仍然保持未啟用狀態。
資料字典DBA_QUEUE_TABLES中記錄了佇列對應的例項資訊,另外在RAC環境中,apply coordinator程式,以及其對應的apply reader server和apply servers執行在相同例項上。
提示:
什麼是 Reader Server :並行執行服務,capture程式的一部分,用來讀取redolog並定位其範圍。
什麼是 Apply Servers :apply程式的一部分,包含一個或多個並行執行服務,用於應用LCRs或傳送其至適當的apply handlers。
什麼是 Apply Coordinator Process :做為apply程式的一部分同屬oracle後臺程式,用於從Reader Server中獲取事務併傳送給Apply Servers。======================================
一步一步學Streams(6) 第一部分 基礎之應用程式(上)
一步一步學Streams(5) 第一部分 基礎之傳播程式(下)
一步一步學Streams(4) 第一部分 基礎之傳播程式(上)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7607759/viewspace-553513/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一步一步學Streams(6) 第一部分 基礎之應用程式(上)
- 一步一步學Streams(3) 第一部分 基礎之捕獲程式
- 一步一步學Streams(5) 第一部分 基礎之傳播程式(下)
- 一步一步學Streams(1) 第一部分 基礎之概述篇
- 一步一步學Streams(14) 第二部分 實踐之移除Streams複製環境
- 一步一步學Streams(13) 第二部分 實踐之建立全庫複製(3)測試
- 一步一步學DataGuard(2)基礎之術語再瞭解大概
- 一步一步學Streams(10) 第二部分 實踐之準備工作(2)初始化環境
- 一步一步學Streams(11) 第二部分 實踐之建立全庫複製(1)準備工作
- 一步一步學Streams(12) 第二部分 實踐之建立全庫複製(2)執行建立
- lucene第一步,lucene基礎,索引建立索引
- 學習程式設計第一步 零基礎上手Python開發程式設計Python
- PyCharm入門第一步(二):除錯第一個Python應用程式PyCharm除錯Python
- PyCharm入門第一步(三):測試第一個Python應用程式PyCharmPython
- 一步一步學RMAN第五篇 RMAN基礎知識補充 一
- 一步一步學RMAN第七篇 RMAN基礎知識補充 二
- 一步一步學DataGuard(5)物理standby之建立示例
- 一步一步學DataGuard(14)邏輯standby之switchover
- 一步一步學ROP之Android ARM 32位篇Android
- 一步一步學ROP之linux_x64篇Linux
- 一步一步學ROP之linux_x86篇Linux
- 一步一步學DataGuard(13)邏輯standby之建立示例
- 一步一步學DataGuard(15)邏輯standby之failoverAI
- 一步一步分析vue之observeVue
- 一步一步搭建react應用-前後端初始化React後端
- 一步一步完成Flutter應用開發-掘金App首頁FlutterAPP
- 融合應用11.1.8安裝,一步一步的引導
- 一步一步學spring bootSpring Boot
- [零基礎學JAVA]Java SE應用部分-35.JAVA類集之四Java
- 【AI開發第一步】微軟認知服務API應用AI微軟API
- 一步一步分析vue之$mount(1)Vue
- 一步一步學RMAN第11篇 rman筆記之綜述筆記
- 一步一步學DataGuard(25)RMAN備份來建立之實踐
- 用 Java 一步一步建造自己的聊天室軟體(第一話) (Yinyin) (轉)Java
- 一步一步分析vue之_data屬性Vue
- 一步一步完成Flutter應用開發-掘金App文章詳情完善FlutterAPP
- 一步一步將支付寶整合到 react-native 應用React
- 【一步一步瞭解你——泛型的應用(機房重構)】泛型