轉載ORA-01591錯誤故障處理(ji)
ORA-01591 錯誤故障處理
摘要 :
在訪問某些表的特定行時報ORA-01591錯誤
select * from BF_INCOME_EXPENSES_T
where account_id = 36816153
and user_id = 39964213
and city_code = '185'
ORA-01591: 鎖定已被有問題的分配事務處理 72.0.1608712 掛起
SQL> select count(*) from UNITELE.BI_MQSYNC_SOURCE_CONTROL_T1;
ORA-01591: 鎖定已被有問題的分配事務處理 72.0.1608712 掛起
由於該表是業務關鍵表,部分前臺業務受到影響。
關鍵詞: ORA-01591 DBA_2PC_PENDING 分散式事務
1. 故障分析
首先,在遇到ORA錯誤時,我們不可能知道每個ORA錯誤都是什麼意思,所以透過oracle的聯機文件查錯誤的cause和action可以讓我們初步瞭解該錯誤。
01591, 00000, "lock held by in-doubt distributed transaction %s"
// *Cause: Trying to access resource that is locked by a dead two-phase commit
// transaction that is in prepared state.
// *Action: DBA should query the pending_trans$ and related tables, and attempt
// to repair network connection(s) to coordinator and commit point.
// If timely repair is not possible, DBA should contact DBA at commit
// point if known or end user for correct outcome, or use heuristic
// default if given to issue a heuristic commit or abort command to
// finalize the local portion of the distributed transaction.
Oracle 對ORA-01591錯誤的描述是"lock held by in-doubt distributed transaction %s,由分散式事務持有鎖造成的。透過錯誤的cause可以看到’Trying to access resource that is locked by a dead two-phase commit transaction that is in prepared state’該錯誤是由訪問一個處於prepared狀態的二階段事務所持有鎖的資源造成的。
下面簡單介紹一下分散式事務。
分散式事務,簡單來說,是指一個事務在本地和遠端執行,本地需要等待確認遠端的事務結束後,進行下一步本地的操作。如透過dblink update遠端資料庫的一行記錄,如果在執行過程中網路異常,或者其他事件導致本地資料庫無法得知遠端資料庫的執行情況,此時就會發生in doublt的報錯。此時需要dba介入,且需要分多種情況進行處理。
分散式事務的,會經歷3個階段:
1.PREPARE PHASE :
1.1 決定哪個資料庫為commit point site。(注,引數檔案中commit_point_strength值高的那個資料庫為commit point site)
1.2 全域性協調者(Global Coordinator)要求所有的點(除commit point site外)做好commit或者rollback的準備。此時,對分散式事務的表加鎖。
1.3 所有分散式事務的節點將它的scn告知全域性協調者。
1.4 全域性協調者取各個點的最大的scn作為分散式事務的scn。
至此,所有的點都完成了準備工作,我們開始進入COMMIT PHASE階段,此時除commit point site點外所有點的事務均為in doubt狀態,直到COMMIT PHASE階段結束。
2.COMMIT PHASE
:
2.1 Global Coordinator將最大scn傳到commit point site,要求其commit。
2.2 commit point嘗試commit或者rollback。分散式事務鎖釋放。
2.3 commit point通知Global Coordinator已經commit。
2.4 Global Coordinator通知分散式事務的所有點進行commit。
3.FORGET PHASE
:
3.1 參與的點通知commit point site他們已經完成commit,commit point site就能忘記(forget)這個事務。
3.2 commit point site在遠端資料庫上清除分散式事務資訊。
3.3 commit point site通知Global Coordinator可以清除本地的分散式事務資訊。
3.4 Global Coordinator清除分散式事務資訊。
有關分散式事務的詳細資訊請參閱oracle聯機文件.
當前的分散式事務處於 Two-Phase Commit 機制中的prepared階段,這個階段事務已經在表上加鎖了, 現在我們要訪問這些表,但事務沒有結束,一直持有鎖,導致訪問資源失敗報ORA-01591。(在這裡需要指出:分散式事務所持有的鎖之所以堵塞讀操作,是因為oralce不知道該顯示哪個版本的資料) 如果結束這個事務,那相應的鎖也會釋放,這樣就能解決這個問題。我們知道要結束一個事務有兩種辦法:commit和rollback。現在我們嘗試結束這個事務:
commit force '72.0.1608712';
ORA-02058: no prepared transaction found with ID 72.0.1608712
報錯並沒有發現prepared狀態的事務,由於該事務是分散式事務,我們首先想到的是dba_2pc_pending這個試圖
SQL> select * from dba_2pc_pending;
no rows selected
該試圖並沒有查到資訊,所以我們無法用commit force結束這個分散式事務,那麼現在我們檢視是否存在該事務, 透過實際報錯,我們可以清晰的看到事務號為72.0.1608712,該事務在72號回滾段的0號事務槽上並且序列號是1608712, 這時查詢一個基表x$ktuxe,看看72號回滾段上是否有該事務。
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
2 KTUXESTA Status,
3 KTUXECFL Flags
4 FROM x$ktuxe
5 WHERE ktuxesta!='INACTIVE'
6 AND ktuxeusn= 72;
KTUXEUSN KTUXESLT KTUXESQN STATUS FLAGS
---------- ---------- ---------- ---------------- ------------------------
72 0 1608712 PREPARED SCO|COL|REV|DEAD
透過x$ktuxe這個基表,我們看到確實存在這個事務,而且是prepared狀態。
此時,我們基本清楚了這個問題的原因:當一個分散式事務死掉時,由於該事務沒有正常結束,導致事務持有的鎖一直沒有釋放,所以在訪問這個事務涉及的資源時,申請不到鎖資源,所以報ORA-01591。由於是分散式事務,當在dba_2pc_pending中查詢不到事務資訊時,我們是無法透過commit或者rollback結束該事務。
所以,我們目前的任務是模擬出這個分散式事務。由於dba_2pc_pending試圖是依賴於pending_trans$這個表,同時事務是與session關聯在一起的,所以我們需要手工往pending_trans$和pending_sessions$兩個表中插入資料。
2. 故障處理
SQL> alter system disable distributed recovery;
系統已更改。
SQL> insert into pending_trans$ (
2 LOCAL_TRAN_ID,
3 GLOBAL_TRAN_FMT,
4 GLOBAL_ORACLE_ID,
5 STATE,
6 STATUS,
7 SESSION_VECTOR,
8 RECO_VECTOR,
9 TYPE#,
10 FAIL_TIME,
11 RECO_TIME)
12 values( '72.0.1608712',
13 306206,
14 'XXXXXXX.12345.1.2.3',
15 'prepared','P',
16 hextoraw( '00000001' ),
17 hextoraw( '00000000' ),
18 0, sysdate, sysdate );
已建立 1 行。
SQL> insert into pending_sessions$
2 values( '72.0.1608712',
3 1, hextoraw('05004F003A1500000104'),
4 'C', 0, 30258592, '',
5 146
6 );
已建立 1 行。
SQL> commit;
提交完成。
SQL> alter system enable distributed recovery;
系統已更改。
此時,查詢dba_2pc_pending發現已有該事務,並且狀態是我們模擬出的prepared狀態
SQL> select * from dba_2pc_pending;
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIX A TRAN_COMMENTFAIL_TIME FORCE_TIME RETRY_TIME OS_USER
OS_TERMINAL HOST DB_USER
COMMIT#
----------------
72.0.1608712 XXXXXXX.12345.1.2.3 prepared no12-11 月-08 12-11月-08
此時我們結束這個事務
SQL> COMMIT FORCE '72.0.1608712';
提交完成。
再次查詢dba_2pc_pending,發現事務是forced commit狀態,該事務已經結束。
SQL> select * from dba_2pc_pending;
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIX A TRAN_COMMENTFAIL_TIME FORCE_TIME RETRY_TIME OS_USER
OS_TERMINAL HOST DB_USER COMMIT#
----------------
72.0.1608712 XXXXXXX.12345.1.2.3 forced commit no12-11 月-08 12-11月-08 12-11月-08
透過x$kutxe 查詢事務資訊,發現事務釋放了回滾段,事務已經結束。
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
2 KTUXESTA Status,
3 KTUXECFL Flags
4 FROM x$ktuxe
5 WHERE ktuxesta!='INACTIVE'
6 AND ktuxeusn= 72;
未選定行
此時,我們需要清除dba_2pc_pending中分散式事務的殘餘資訊
SQL> alter session set "_smu_debug_mode"=4; ―― 在session級別設定回滾段處於手工管理模式,如果不設定這個引數,在回滾段自動管理模式下,清除事務資訊會報錯
會話已更改。
SQL> execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('72.0.1608712'); ――用dbms包清除事務資訊
PL/SQL 過程已成功完成。
SQL> select * from dba_2pc_pending;
未選定行
測試訪問業務表
SQL> select count(*) from UNITELE.BI_MQSYNC_SOURCE_CONTROL_T1;
COUNT(*)
----------
367
問題解決。
其實,我在另外一個客戶處也碰到過類似問題,當時也是報ORA-01591,但是在dba_2pc_pending中可以查到prepared狀態的事務,此時只需要commit force結束這個事務,並清除事務資訊就可以了。對於上面的案例,我懷疑開發商直接清除了分散式事務資訊,但是事務並沒有結束,導致鎖資源得不到釋放報ORA-01591。
總結: ORA-01591 錯誤一般是由於分散式事務造成的,造成分散式事務失敗的原因主要是庫之間的網路突然中斷,造成兩個庫中的事務資訊不一致,所以會有殘餘的分散式事務資訊。此時,要針對不同的事務狀態做不同的處理。同時在遇到棘手的問題時,可以查詢metalink,該案例參考metalink文件:NOTE:
[@more@]
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/48010/viewspace-1016050/,如需轉載,請註明出處,否則將追究法律責任。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29863023/viewspace-2779761/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ORA-01591錯誤故障處理
- hbase 故障的處理方案。 (轉載文章)
- [轉] Scala Try 與錯誤處理
- 【故障處理】ORA-31600和ORA-04063錯誤
- 錯誤處理
- [20181031]模擬ora-01591錯誤.txt
- Python錯誤處理Python
- PHP 錯誤處理PHP
- php錯誤處理PHP
- Go 錯誤處理Go
- 錯誤處理:如何通過 error、deferred、panic 等處理錯誤?Error
- openGauss 處理錯誤表
- go的錯誤處理Go
- axios 的錯誤處理iOS
- Python錯誤處理和異常處理(二)Python
- Oracle異常錯誤處理Oracle
- 淺談前端錯誤處理前端
- ORACLE 異常錯誤處理Oracle
- PHP 核心特性 - 錯誤處理PHP
- 15-錯誤處理(Error)Error
- Go語言之錯誤處理Go
- grpc中的錯誤處理RPC
- laravel9 錯誤處理Laravel
- 學習Rust 錯誤處理Rust
- 【故障處理】如何避免在執行impdp後出現ORA-00001錯誤
- rust學習十、異常處理(錯誤處理)Rust
- 【故障處理】ORA-600:[13013],[5001]故障處理
- node端統一錯誤處理
- node錯誤處理與日誌
- js錯誤處理權威指北JS
- [譯] 使用 Catcher 處理 Flutter 錯誤Flutter
- 如何處理錯誤訊息PleaseinstalltheLinuxkernelheaderfilesLinuxHeader
- 錯誤碼全域性處理(二)
- 錯誤碼全域性處理(一)
- PHP安裝後錯誤處理PHP
- 常用模組 PHP 錯誤處理PHP
- Restful API 中的錯誤處理RESTAPI
- 請教 Element 的錯誤處理