HANDLECOLLISIONS在官方文檔上的說明:
使用HANDLECOLLISIONS和NOHANDLECOLLISIONS參數來控制在目標上應用SQL時,Replicat是否嘗試解決重復記錄和缺少記錄的錯誤。
事實是, HANDLECOLLISIONS 經常被爛用。為了省事,許多運維人員,經常在目標端投遞出問題時,直接在目標端進程上配置 HANDLECOLLISIONS,然后進程就會啟動並繼續執行,但這樣做只會掩蓋問題,並且隨着時間的遷移,問題越積越深,最終發現目標端的數據與源端相差很遠。
所以 HANDLECOLLISIONS 根據官方的建議,一般只應該用在初始化階段的replicat進程。如果在其它時候使用 HANDLECOLLISIONS,這是非常不明智的做法,因為極有可能會造成數據不一致。
如果有這種情況,應該立即停止投遞進程並刪除HANDLECOLLISIONS參數,然后對源和目標端的數據進行對比后重新同步。
要使用 HANDLECOLLISIONS,還需要在源端進程和表的附加日志上做些工作,包括:
1.HANDLECOLLISIONS 只在有PK或唯一索引的表上有效,如果是沒有唯一鍵的表,則可能造成重復記錄。
2.在抽取進程使用LOGALLSUPCOLS參數,並針對表打開全字段附加日志,如果沒有這樣設置,當 HANDLECOLLISIONS 將update操作轉換為insert操作時,可能會報ORA-1403錯誤。
3.如果表上有LOB字段,且存的內容超過緩沖區域(2 kb或4 kb)的大小,則 HANDLECOLLISIONS 會排除此LOB字段的處理,所以,如果有表包含有lob字段,且長度超過2Kb,則不應該使用 HANDLECOLLISIONS。
所以, HANDLECOLLISIONS 最好是在初始化時使用,且初始化追平之后就應該停止使用。下面基於一個示例來講解:
如果在下午1點啟動抽取進程,2點的時候,在確保沒有1點之前開始且到2點還沒有結束的事務,此時,使用SourceIsTable進行初始化。在初始化的過程中,系統上一般會有數據變化。
下午3點的時候初始化完成,現在在目標端使用 HANDLECOLLISIONS 參數,啟動投遞進程。此時,投遞進程會從隊列文件(增量數據)最開始的地方(1點)開始應用數據到目標端DB,理論上1-2點之間變化的數據在OGG增量數據和初始化數據中都有包含。比如,有人在1:15開始一個事務,1:30才結束,在OGG的extract增量數據及initial load中都會包含這個交易的數據。此時,因為有使用 HANDLECOLLISIONS ,所以replicat會根據沖突處理機制,自動處理這些重復數據,確保目標端數據一致。
一旦目標端replicat進程處理到初始化結束的時間點,即3點,則應該立即使用 SEND REPLICAT NOHANDLECOLLISIONS 去掉自動沖突解決機制,並將 HANDLECOLLISIONS 參數從replicat進程中刪除。