一步一步學Streams(6) 第一部分 基礎之應用程式(上)
有捕獲,有傳播,接下來應該就是應用了,真巧,ORACLE也是這麼想的。在Streams複製環境中,共享物件的修改正是按照這樣的邏輯被捕獲->傳播->應用。你可以在目標端配置一個或多個apply程式應用這些修改,下面我們再通過一些文字描述一下這個流程。
Apply 程式也是oracle的後臺程式,專門出隊並應用LCRs地幹活。應用LCRs是由專門的apply user負責,apply user即可以通過自定義規則執行應用,也可以通過apply handler。
1. LCRs 應用選項
Apply 程式提供了非常靈活的機制處理LCRs,因此你可能需要針對不同配置情況做不同的選擇,比如前面在講傳播時就曾提到的,單個apply程式要麼應用捕獲的LCR,要麼應用user-enqueued LCR,而不能同時應用二者(如果某佇列同時包含兩種LCR的話,則應用端至少需要兩個apply程式),你可以使用DBMS_STREAMS_ADM/DBMS_APPLY_ADM包建立apply程式應用捕獲LCRs,如果要應用user-enqueued LCRs,則必須使用DBMS_APPLY_ADM.CREATE_APPLY過程建立應用程式。
下面分別介紹不同應用:
A 、自動應用(Direct Apply)
顧名思議即自動執行無須使用者干預。Apply程式要麼成功應用LCR中的修改到資料庫物件,要麼應用時出錯,出錯的話將由conflict handler或使用者自定義的error handler接管處理。
如果conflict handler能夠解決衝突問題,其要麼應用LCR,要麼放棄相關修改。如果error handler能夠處理錯誤,則應用該LCR,否則apply程式將該事務及LCRs相關的所有事務統統置入一個錯誤佇列,等待使用者手工處理,後面我們會有例子演示。
B 、自定義應用(Custom Apply)
指Apply程式將lcr做為引數傳送到使用者自定義的過程中處理。使用者自定義的處理row LCRs中DML語句的過程被稱為DML handler,處理DDL LCRs中DDL語句的過程被稱為DDL handler。一個apply程式可以有多個DML handlers,但是隻能有一個DDL handler。
自定義應用非常靈活,你甚至可以為每個表的不同型別操作指定不同的DML handler處理。比如為hr.employees表的insert操作指定一個DML handler,為其update操作指定另一個DML handler。又比如你希望在某個目標庫中跳過對hr.employees的delete操作,可以通過自定義DML handler的方式專門處理delete操作來實現這一目的。另外注意通常DML handler中不應有事務提交或回滾,除非是顯式指定的savepoint。
另外對於DML/DDL handler,你可以指定一個precommit handler,該handler也是一個pl/sql實現的過程,其功能是從internal commit獲取commit SCN。precommit handler能夠以自定義的方式處理提交資訊。
提示:
不要通過DML handlers/error handlers/自定義規則函式修改LONG,LONG RAW,nonassembled LOB列。2. 依賴關係
下面分別描述apply程式應用過程中對關聯項的處理
2.1. 應用時關聯的事務如何處理。
Apply 程式的parallelism引數控制應用的並行度。比如當該引數設定為1的時候,則只有一個apply程式按照事務在源端順序一步步執行,這種情況下其實不需要考慮關聯事務的問題,因為此時相當於是在串聯執行,即不會有衝突也不會堵塞。需要注意的是當parallelism不為1時,多個apply程式可能同時應用多個事務,這些事務之間可能是有依賴和關聯的,比如說源端a事務在b事務之前提交,但是目前端應用時為了提高應用效率,可能a/b兩事務分別被不同apply程式同時呼叫,這個時候呼叫b事務的apply程式必然會等待呼叫a事務的apply程式執行完成了,再應用b事務中的修改。Apply程式會自動判斷事務間的關聯性。
- 提示:parallelism引數可以通過DBMS_APPLY_ADM.SET_PARAMETER過程設定。
2.2. 應用 Row LCR 時的順序
分幾種情況:
- 單事務情況下Row LCR應用順序與源端相同序。
- 有事務依賴的情況下Row LCR應用順序可見上節:應用時關聯的事務如何處理
- 如果apply程式的commit_serialization引數設定為full,則apply程式按照源端的執行順序提交所有事務,不管事務是否有關聯的Row LCRs。如果apply程式的commit_serialization引數設定為none,則apply程式有可能忽略依賴項直接應用,因此應用順序有可能與源端不同。
- 提示:commit_serialization引數也可以通過DBMS_APPLY_ADM.SET_PARAMETER過程設定。
2.3. 約束的處理
如果要更新的物件在目標端存在同名物件並且schema也相同,並且目標端物件定義了約束,apply程式會自動檢測其在row LCRs中的依賴關係。
不管commit_serialization和parallelism引數值如何設定,apply程式總會優先考慮物件約束問題。比如apply程式應用一個事務時發現該事務包含的row LCRs依賴於另一個事務的row LCRs,則apply程式必須保證row LCRs以正確的順序提交。
2.4. 定義虛擬依賴(Virtual Dependency Definitions)
某些情況下,apply程式需要一些附加資訊來檢查並行應用情況下row LCRs中物件的關聯情況,比如:
- Apply 程式在目標端資料字典中找不對要更新的物件,這很正常,因為streams非常靈活,你可以配置從源端的一個物件複製到目標端另一個非同名物件中,當然這種情況下應用時就會比較複雜,比如說觸發前面說的apply程式找不著要更新物件的問題。
- 資料未正確格式化,比如說單條row LCR中的sql語句實際觸發更新多個表的資料。
如果apply程式未檢查正確檢測到依賴關係的話,應用錯誤或錯誤處理也可能執行。某些情況下上述的兩種情況可以通過rule-based轉換避免。比如說針對要更新的物件在源端和目標端並不存在於相同schema的情況,rule-based轉換也能夠在應用前修改schema。Rule-based轉換的短板在於其不能適用於並行處理的情況。下面,主角登場,大家鼓掌,它就是。。。。。
Virtual dependency definition ,其實就是專用於apply程式的物件依賴資訊的描述,用來在目標端檢查事務間的關聯性。Virtual dependency definitions不是以約束形式存在於目標端資料庫,而是通過DBMS_APPLY_ADM包指定。Virtual dependency definitions提供了apply程式正確應用LCRs所需的必要資訊,可以定義如下兩種型別:
- Value Dependency
Value dependency 定義了一個表的約束,用來描述一個或從外表之間列的關聯關係。Value dependency是一個或多個列的集合,apply程式通過value dependency來檢查這些列在row LCRs之間的關聯。Value dependency還可以定義虛擬的外來鍵,只不過與真正的外來鍵約束不同的是,value dependency定義的虛擬外來鍵甚至可以同時關聯多個表。如果目標端列之間關聯關係未被明確通過約束等方式指定的話,Value dependency就能派上用場了,value dependency就是用來描述這些關聯關係的。
定義value dependency可以通過DBMS_APPLY_ADM.SET_VALUE_DEPENDENCY過程,後續章節中會有示例詳細說明。
Value dependency 有限制條件,一個value dependency中定義的物件關聯關係不能跨多個資料庫,同時,value dependency定義的列在源端必須開啟附加日誌,無條件記錄這些列的所有操作。
- Object Dependency
Object dependency 定義兩個物件間的父子關聯關係。Apply程式在所有lower CSCN(commit system change number)涉及的父物件提交後執行事務關聯的子物件。Apply程式使用row LCR中的物件標識檢查依賴,而不是通過列值。如果目標端資料庫表之間沒有通過約束等方式定義關聯關係的話(value dependency是當列之間),Object dependency就能派上用場。
可以通過DBMS_APPLY_ADM.CREATE_OBJECT_DEPENDENCY過程在目標端建立物件依賴,使用DBMS_APPLY_ADM.DROP_OBJECT_DEPENDENCY過程刪除物件依賴。
2.5. Barrier Transactions
如果apply程式不能識別LCR中要更新的物件(即不存在於目標端資料庫資料字典,也沒有定義VDD),則該事務所包含的row LCR需要等到相同lower CSCN值的其它所有事務提交後再被應用,這種事務就被稱為Barrier transaction。其它CSCN值高於該事務的也不會被應用,直到Barrier transaction提交。
3. 應用DML修改
3.1. 限制條件
必須確保主鍵列在源端操作時都被記錄到redolog中,有多種方法能夠確保操作被記錄到redolog,比如附加日誌。目標端的複合唯一鍵或外來鍵約束在源庫端必須需要啟用附加日誌。單列唯一鍵或外來鍵則不需要,不過,如果源端約束列有多個,你也必須建立附加日誌。
3.2. Substitute Key Columns
應儘可能給所有會被捕獲的表建立主鍵或唯一鍵,前面捕獲的部分三思已經介紹過相關內容,到應用的環節某些理論同樣適用,比如說在應用/檢測衝突等等時,oracle必須能夠識別唯一列的資訊,不然應用也無從做起。
預設情況下,Streams通過主鍵來唯一記錄,如果沒有定義主鍵,則通過最小的非空唯一鍵來確定記錄唯一。如果上述兩者都沒有,你可以在目標端通過指定substitute key來唯一記錄。
可以通過DBMS_APPLY_ADM.SET_KEY_COLUMNS過程設定substitute主鍵列,與真正的主鍵不同,substitute key列可以包含空值,並且substitute key列在應用時擁有更高的優先順序,不過需要注意,如果你在目標端為表建立的substitute key引用列在源端表中並非是主鍵,那麼務必在源端為該表啟用附加日誌。如果表即無主鍵也無唯一鍵,並且也未建立substitute key,那麼apply程式會將該表除lob,long,long raw型別列除外的所有列組合在一起做為關鍵列,並且源端也必須為該表啟用附加日誌。
- 提示:oracle建議做為substitute key的列最好為非空列,並且為substitute key引用列建立索引以提高效能。
3.3. 列有差異時的應用
列差異是說源端和目標端相同表中列定義不同(可能是型別/長度不同,也可能是列名不存在),如果說streams複製環境中存在這種情況,一般可以通過rule-based轉換或者DML handler處理器,下列各項描述的apply程式遇到列差異時的處理行為。
3.3.1. 列在目標端不存在如果要更新的列在目標端不存在,則apply程式丟擲異常並移動該事務到error queue。這種問題可以通過建立rule-based轉換或者配置DML handler,通過DELETE_COLUMN過程在應用前將列所在LCRs中不存在的列刪除。
3.3.2. 列在源端不存在如果目標端的表擁有源端不存在的列,apply程式要視多出的列是否影響應用來決定其操作。如果額外列不影響應用的依賴關係,則apply程式直接應用修改。對於insert的操作如果額外列如果有預設值的話則插入預設值,否則該列值為null。
如果額外列影響應用,則apply程式也會將該事務置入error queue。
3.3.3. 列型別不同如果源端與目標端表中列的型別不同,apply程式應用時也會丟擲錯誤並將事務置入error queue。要避免這種錯誤發生,也可以通過建立自定義的rule-based轉換或DML handler處理。
3.4. 索引組織表的應用
Apply 程式只支援對不含下列ROWID,UROWID,User-defined types型別的索引組織表應用修改,如果含有上述類似,則應用時也會丟擲異常。
3.5. 解決衝突
多源的streams複製環境中有衝突是正常的,例如,在源端某表的記錄被更新,同時目標端同名表的這些記錄也被更新,當修改被傳播到各自目標端的時候,apply程式在應用前就必須明確究竟是應用修改,還是保留本地的資料。Streams會自動檢測衝突,對於update衝突如果配置了conflict handler會嘗試使用解決。Streams提供了多種衝突解決方案,允許你根據自己的規則進行定製。
3.6. Handler 處理Row LCR
DML handler/Error handler/Update conflict handler 都可以處理row LCRs,不過注意同一個表的同一個操作不能同時定義DML handler和Error handler,下面分別描述配置了不同handler時的處理情況:
3.6.1. 沒有配置handler如果沒有配置任何handler,apply程式直接應用row LCR,如果成功則表被更新,如果失敗則應用事務回滾並移動至錯誤佇列。
3.6.2. Update conflict handler這種情況下apply程式也是嘗試直接應用row LCR,如果成功則表被更新,如果由於非更新衝突(比如非唯一衝突或delete衝突)造成應用失敗,則該事務回滾並移動至錯誤佇列。如果由於更新造成失敗,則update conflict handler被呼叫,如果update conflict handler能夠解決衝突問題,則apply程式按照你配置了衝突解決方案應用或丟棄LCR,並繼續應用該事務中其它LCRs。如果update conflict handler不能解決問題,則事務同樣回滾並移動至錯誤佇列。
3.6.3. DML handler這種情況下DML handler完全控制row LCR的處理。某些DML handler能夠執行SQL操作或者執行EXECUTE member procedure。如果DML handler執行EXECUTE member procedure,則apply程式嘗試應用row LCR。
提示:
什麼是 EXECUTE Member Procedure , 即在預設使用者下執行 LCR。使用該方式應用LCR時,其它嘗試應用該LCR的apply程式統統被該Apply程式接管處理,這就是前面說的完全控制row LCR的處理。如果DML handler執行的SQL操作失敗,或者嘗試執行EXECUTE member procedure失敗,則DML handler嘗試處理這種異常。如果DML handler沒有報出異常,則apply程式就認為DML handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR。
如果DML handler不能處理異常,則將錯誤丟擲,該事務回滾並移動至錯誤佇列。
3.6.4. DML handler + Update conflict handler這種情況下與單獨配置DML handler相似,區別只在於如果DML handler執行的SQL操作失敗,或者嘗試執行EXECUTE member procedure遇到非update conflict導致的失敗,則DML handler嘗試處理這種異常。如果DML handler沒有報出異常,則apply程式就認為DML handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR。
如果由於update衝突導致EXECUTE member procedure執行失敗,視EXECUTE member procedure引數conflict_resolution引數值的設定,apply程式執行不同的操作:
- Conflict_resolution 引數值設定為true:update conflict handler被呼叫。如果update conflict handler能夠處理衝突,並且其它操作也都成功執行,則apply程式繼續應用其它row LCRs,如果update conflict handler不能解決衝突問題,則DML handler嘗試處理器,如果DML handler沒有報出異常,則apply程式就認為DML handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR,如果DML handler不能處理異常,則將錯誤丟擲,該事務回滾並移動至錯誤佇列。
- Conflict_resolution 引數值設定為false:update conflict handler不會被呼叫,DML handler嘗試處理這種異常。如果DML handler沒有報出異常,則apply程式就認為DML handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR,如果DML handler不能處理異常,則將錯誤丟擲,該事務回滾並移動至錯誤佇列。
這種情況下由Error handler負責row LCR的處理,與DML handler類似,Error handler完全控制處理過程Error handler能夠執行SQL操作或者執行EXECUTE member procedure。如果Error handler執行EXECUTE member procedure,則apply程式嘗試應用row LCR。
如果Error handler執行的SQL操作失敗,或者嘗試執行EXECUTE member procedure失敗,則Error handler嘗試處理這種異常。如果Error handler沒有報出異常,則apply程式就認為Error handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR。
如果Error handler不能處理異常,則將錯誤丟擲,該事務回滾並移動至錯誤佇列。
3.6.6. Error handler + Update conflict handler這種情況下呼叫哪種handler去處理取決於錯誤型別:
- 如果是非update衝突導致的錯誤,則呼叫Error handler處理,處理規則同前小節Error handler。
- 如果是update衝突導致的錯誤,則呼叫Update conflict handler處理。如果update conflict handler能夠處理衝突,則apply程式繼續應用其它row LCRs,這種情況下不會再呼叫Error handler。如果update conflict handler不能解決衝突問題,則Error handler嘗試處理,如果DML handler沒有報出異常,則apply程式就認為Error handler為row LCR執行了正確的操作,apply程式繼續應用該事務中其它row LCR,如果DML handler不能處理異常,則將錯誤丟擲,該事務回滾並移動至錯誤佇列。
======================================
一步一步學Streams(5) 第一部分 基礎之傳播程式(下)
一步一步學Streams(4) 第一部分 基礎之傳播程式(上)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7607759/viewspace-550355/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一步一步學Streams(7) 第一部分 基礎之應用程式(中)
- 一步一步學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基礎知識補充 一
- 一步一步用Delphi6實現Web Service (轉)Web
- 一步一步學RMAN第七篇 RMAN基礎知識補充 二
- 一步一步學DataGuard(5)物理standby之建立示例
- 一步一步學DataGuard(14)邏輯standby之switchover
- Java基礎部分6Java
- 一步一步學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備份來建立之實踐
- 用js實現返回上一步操作JS
- Wi-Fi 6落地第一步 思科率先佈局
- 用 Java 一步一步建造自己的聊天室軟體(第一話) (Yinyin) (轉)Java