在Oracle中,分散式事務ORA-01591錯誤如何解決?

  • 2019 年 11 月 23 日
  • 筆記

題目部分

在Oracle中,分散式事務ORA-01591錯誤如何解決?

答案部分

1、故障環境介紹

項目

資料庫

DB類型

RAC

DB版本

11.2.0.3

DB存儲

ASM

OS版本及kernel版本

AIX 64位 6.1.0.0

2、故障發生現象及報錯資訊

有同事發來錯誤,截圖如下:

執行一個UPDATE語句的時候報ORA-01591的錯誤。

3、故障分析及解決過程

這個錯誤是由於分散式事務引起,而不是普通的鎖引起的。若檢查一般對象數據表鎖定,則只需要檢查V$LOCKED_OBJECT和V$TRANSACTION視圖,就可以定位到具體的SQL語句和操作人等資訊,但是檢查之後的結果如下:

1SYS@oraLHR12> SELECT * FROM GV$LOCKED_OBJECT;  2no rows selected  3SYS@oraLHR12> SELECT * FROM GV$TRANSACTION;  4no rows selected

兩個關鍵視圖中,沒有鎖定的對象,也沒有正在進行未提交的事務。那是不是沒有鎖定呢?或者鎖已經釋放了,重新嘗試對數據表加鎖,如下所示:

1SYS@oraLHR12> SELECT * FROM LHR.LHRBOKBAL FOR UPDATE;  2select * from LHR.LHRBOKBAL for update  3                   *  4ERROR at line 1:  5ORA-01591: lock held by in-doubt distributed transaction 20.13.14721  6SYS@oraLHR12> SELECT COUNT(1) FROM LHR.LHRBOKBAL;  7  COUNT(1)  8----------  9  30998411

系統沒有像一般阻塞那樣等待,而是報錯ORA-01591的錯誤,並且提示鎖被一個分散式事務持有,不能實現加鎖操作。那麼ORA-01591錯誤究竟是什麼錯誤呢?可以使用Oracle提供的oerr工具查看該錯誤編號,如下所示:

 1root@ZFLHRRSP:/# oerr ora 1591   201591, 00000, "lock held by in-doubt distributed transaction %s"   3// *Cause:  Trying to access resource that is locked by a dead two-phase commit   4//          transaction that is in prepared state.   5// *Action: DBA should query the pending_trans$ and related tables, and attempt   6//          to repair network connection(s) to coordinator and commit point.   7//          If timely repair is not possible, DBA should contact DBA at commit   8//          point if known or end user for correct outcome, or use heuristic   9//          default if given to issue a heuristic commit or abort command to  10//          finalize the local portion of the distributed transaction.  11

簡單的說,01591錯誤的原因是該對象被一個處在「IN-DOUBT」狀態的分散式事務鎖定。分散式事務使用的是「two-phase commit」二階段提交技術。解決該問題的方法就是查看內部表PENDING_TRANS$,確定分散式事務資訊。這種狀態的事務主要是由於在進行分散式事務時候,發生網路突發中斷的情況,引起分散式事務無法正常結束,等待中斷節點的事務響應。於是,各節點的事務所鎖定的表就不會被釋放掉。

此時,檢查視圖DBA_2PC_PENDING(或者基表PENDING_TRANS$),查看是否存在這種情況。

果然,當前存在一個阻塞分散式事務,處在prepared狀態。當前問題,主要是源於在進入prepared階段之後,發生了網路中斷的現象,引起COMMIT的階段不能等待到事務資訊。所以,才會一直處在Prepared狀態,數據表也就不會進行釋放。

對於這個事務,只能通過連接網路或者強制提交回退事務來結束。可以使用COMMIT FORCE或者ROLLBACK FORCE來進行處理,在這裡,進行回滾操作,如下所示:

1SYS@oraLHR12> ROLLBACK FORCE '20.13.14721';  2Rollback complete.

ROLLBACK FORCE的參數是DBA_2PC_PENDING中記錄本地事務資訊的編號即LOCAL_TRAN_ID。

此時,再次查看數據。

此時,該事務狀態已經變化為forced rollback表示已經強制回退,此時再次嘗試鎖定表操作:

116:25:31 SQL> SELECT * FROM LHR.LHRBOKBAL FOR UPDATE;  2CURRENCY  3--------  4001

可以看出已經不報錯了,可以正常執行。

& 說明:

有關該案例的更多內容可以參考我的BLOG:http://blog.itpub.net/26736162/viewspace-2122999/

本文選自《Oracle程式設計師面試筆試寶典》,作者:小麥苗