您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么處理ORACLE懸疑分布式事務(wù)問題”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么處理ORACLE懸疑分布式事務(wù)問題”吧!
當需要在多個Oracle數(shù)據(jù)庫之間進行數(shù)據(jù)一致性操作時,就會用到分布式事務(wù)。
例如:
insert into T_log@remote_db; --遠程數(shù)據(jù)庫插入 insert into T_local; --本地數(shù)據(jù)庫插入 commit;
分布在本地和遠程兩個db的事務(wù)同時操作,這就構(gòu)成了一個分布式事務(wù)。
分布式事務(wù)采用Two-Phase Commit提交機制,保證分布在各個節(jié)點的子事務(wù)能夠全部提交或全部回滾的原子性。在這種機制下,事務(wù)處理過程分為三個階段:
PREPARE:發(fā)起分布式事務(wù)的節(jié)點通知各個關(guān)聯(lián)節(jié)點準備提交或回滾。各關(guān)聯(lián)節(jié)點此時會做三個事情:刷新redo信息到redo log中;將持有的鎖轉(zhuǎn)換為懸疑事務(wù)鎖;取各節(jié)點中最大的SCN號進行同步
COMMIT:寫入commited SCN,釋放鎖資源
FORGET:懸疑事務(wù)表和關(guān)聯(lián)的數(shù)據(jù)庫視圖信息清理
由于分布式事務(wù)涉及到多個數(shù)據(jù)庫之間進行操作,偶爾會遇到一些異常情況(例如系統(tǒng)或網(wǎng)絡(luò)中斷)導(dǎo)致上述三個階段出現(xiàn)異常,這就在一個或多個節(jié)點上,產(chǎn)生不完整的“懸疑分布式事務(wù)”。
大多數(shù)情況下,出現(xiàn)這種問題,Oracle會由Reco進程進行自動修復(fù),Oracle數(shù)據(jù)庫會在dba_2pc_pending 和dba_2pc_neighbors等多個視圖中記錄分布式事務(wù)相關(guān)的信息,事實上reco進程也是基于這些信息去做自動修復(fù)的。
Reco進程會嘗試連接到其他節(jié)點獲取分布式事務(wù)信息,然后嘗試修復(fù)失敗的事務(wù),并將對應(yīng)的事務(wù)中的記錄刪除。
但有些情況下(例如節(jié)點無法正常訪問或事務(wù)表中記錄的數(shù)據(jù)不完整),Reco進程不能正常完成這個工作,就會拋出異常。對于分布式事務(wù),對應(yīng)的異常代碼區(qū)間是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.
此時往往需要手工處理進行干預(yù)。
以下是三種常見的分布式事務(wù)問題場景:
dba_2pc視圖中有數(shù)據(jù),但分布式事務(wù)已經(jīng)不存在
分布式事務(wù)存在,但dba_2pc視圖中沒有數(shù)據(jù)
事務(wù)和視圖數(shù)據(jù)都有,但是執(zhí)行commit force或rollback force時hang住
通過報錯會有提示,例如:
ORA-01591: lock held by in-doubt distributed transaction 10.20.360 這個10.20.360就是我們需要檢查分布式事務(wù)ID
場景一:dba_2pc視圖中有數(shù)據(jù),但分布式事務(wù)已經(jīng)不存在
視圖有數(shù)據(jù),那么先檢查數(shù)據(jù)的狀態(tài)
select * from dba_2pc_pending where local_tran_id='10.20.360';
主要看state字段。
如果事務(wù)已經(jīng)是committed, rollback forced或者commit forced狀態(tài),表示事務(wù)已經(jīng)完成了,但是在FORGET階段處理時,數(shù)據(jù)庫字典的信息沒能及時清除。此時,我們調(diào)用oracle的清理丟失事務(wù)信息的語句就可以完成處理:
execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY ('10.20.360');
如果事務(wù)是PREPARED狀態(tài),但是在事務(wù)表中又沒有活動的事務(wù):
SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */ KTUXESTA Status, KTUXECFL Flags FROM x$ktuxe WHERE ktuxesta!='INACTIVE' AND ktuxeusn= 10; --注意替換這里的回滾段號(xid=usn.slot.(sqn+1)) ----沒有活動的事務(wù)
那此時需要手工清理丟失事務(wù)的信息
set transaction use rollback segment SYSTEM; delete from sys.pending_trans$ where local_tran_id = ; delete from sys.pending_sessions$ where local_tran_id = ; delete from sys.pending_sub_sessions$ where local_tran_id = ; commit;
場景二:分布式事務(wù)存在,但dba_2pc視圖中沒有數(shù)據(jù)
遇到ORA-2054, ORA-1591等錯誤,檢查dba_2pc視圖沒有記錄,這種場景不常見,只在少數(shù)極端的情況下出現(xiàn)。
先確認現(xiàn)象,分別檢查x$ktuxe和 dba_2pc_pending視圖,查詢語句與場景一相同
在這種情況下無論是執(zhí)行commit force還是rollback force,都會直接拋出異常:
commit force '10.20.360'; ORA-02058: no prepared transaction found with ID 10.20.360
這時我們需要將視圖對應(yīng)的基表數(shù)據(jù)補入,然后再執(zhí)行rollback force。
alter system disable distributed recovery; insert into pending_trans$ ( LOCAL_TRAN_ID, GLOBAL_TRAN_FMT, GLOBAL_ORACLE_ID,STATE, STATUS, SESSION_VECTOR,RECO_VECTOR,TYPE#, FAIL_TIME, RECO_TIME) values( '10.20.360', /* <== Replace this with your local tran id */ 306206, 'xxxxxxxx.00000.0.0.0', 'prepared','P', hextoraw( '00000001' ),hextoraw( '00000000' ), 0, sysdate, sysdate ); insert into pending_sessions$ values( '10.20.360',1, hextoraw('00000000'), 'C', 0, 1433927502, '', 14); --1433927502為DBID, 14為userid commit; rollback force '10.20.360'; EXECUTE DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.20.360'); --手工清理事務(wù)信息
場景三:事務(wù)和視圖數(shù)據(jù)都有,但是執(zhí)行commit force或rollback force時hang住
如果視圖和事務(wù)表中都有數(shù)據(jù),而且狀態(tài)是PREPARED,先執(zhí)行commit force或rollback force,通常就能解決問題,但有時候也會遇到執(zhí)行force處理時hang住
嘗試purge事務(wù)信息時,有提示報錯:
BEGIN DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('10.20.360'); END; * ERROR at line 1: ORA-06510: PL/SQL: unhandled user-defined exception ORA-06512: at "SYS.DBMS_TRANSACTION", line 94 ORA-06512: at line 1
此時需要進行場景一和場景二的結(jié)合起來的所有步驟:
1. 先將視圖對應(yīng)的基表數(shù)據(jù)刪除 delete from sys.pending_trans$ where local_tran_id = '10.20.360'; delete from sys.pending_sessions$ where local_tran_id = '10.20.360'; delete from sys.pending_sub_sessions$ where local_tran_id ='10.20.360'; commit; 2. 再插入pending_trans$和pending_sessions$數(shù)據(jù),見場景二 3. rollback force '10.20.360'; 4. Purge the transaction: exec dbms_transaction.purge_lost_db_entry('10.20.360');
感謝各位的閱讀,以上就是“怎么處理ORACLE懸疑分布式事務(wù)問題”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對怎么處理ORACLE懸疑分布式事務(wù)問題這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。