天天看點

Oracle 分布式事務 2pc 故障處理

目錄

我們在使用 oracle 資料庫時,有時候會碰到需要使用分布式事務,并且會碰到一些報錯!

當需要在多個Oracle資料庫之間進行資料一緻性操作時,就會用到分布式事務。

例如:

insert into T_log@remote_db;  --遠端資料庫插入
insert into T_local;          --本地資料庫插入
commit;      

分布在本地和遠端兩個db的事務同時操作,這就構成了一個分布式事務。

分布式事務采用

Two-Phase Commit

送出機制,保證分布在各個節點的子事務能夠全部送出或全部復原的原子性。

在這種機制下,事務處理過程分為三個階段:

  • PREPARE:發起分布式事務的節點通知各個關聯節點準備送出或復原。
  • COMMIT:寫入commited SCN,釋放鎖資源
  • FORGET:懸疑事務表和關聯的資料庫視圖資訊清理

各關聯節點此時會做三個事情:重新整理redo資訊到redo log中;将持有的鎖轉換為懸疑事務鎖;取各節點中最大的SCN号進行同步!

以下是三種常見的分布式事務問題場景:

  • dba_2pc視圖中有資料,但分布式事務已經不存在
  • 分布式事務存在,但dba_2pc視圖中沒有資料
  • 事務和視圖資料都有,但是執行commit force或rollback force時hang住

通過報錯會有提示,例如:

ORA-01591: lock held by in-doubt distributed transaction 10.20.360      

這個10.20.360就是我們需要檢查分布式事務ID!

由于分布式事務涉及到多個資料庫之間進行操作,偶爾會遇到一些異常情況(例如系統或網絡中斷)導緻上述三個階段出現異常,這就在一個或多個節點上,産生不完整的“懸疑分布式事務”。

大多數情況下,出現這種問題,Oracle 會由 Reco 程序進行自動修複,Oracle 資料庫會在

dba_2pc_pending

dba_2pc_neighbors

等多個視圖中記錄分布式事務相關的資訊,事實上 reco 程序也是基于這些資訊去做自動修複的。

Reco

程序會嘗試連接配接到其他節點擷取分布式事務資訊,然後嘗試修複失敗的事務,并将對應的事務中的記錄删除。

但有些情況下(例如節點無法正常通路或事務表中記錄的資料不完整),Reco 程序不能正常完成這個工作,就會抛出異常。

對于分布式事務,對應的異常代碼區間是

ORA-02040 - ORA-02099

,可通過alert日志檢視到錯誤資訊。

ORA-02054: transaction in-doubt
The transaction is neither committed or rolled back locally, and we have lost communication with the global coordinator.      

此時往往需要手工處理進行幹預。

常用的 2pc_clean 指令如下:

select 'rollback force '||''''||local_tran_id||''''||';' "RollBack"
       from dba_2pc_pending
       where state='prepared';

select 'exec dbms_transaction.purge_lost_db_entry('||''''||local_tran_id||''''||');' "Purge"
       from dba_2pc_pending;

select 'rollback force  ''' || LOCAL_TRAN_ID || ''';' || chr(10) ||
'execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY(''' || LOCAL_TRAN_ID
 || ''');' || chr(10) || 'commit;' from DBA_2PC_PENDING;