<b>【故障處理】分布式事務ORA-01591錯誤解決</b><b></b>
各位技術愛好者,看完本文後,你可以掌握如下的技能,也可以學到一些其它你所不知道的知識,~O(∩_∩)O~:
① 分布式事務的簡單概念
② ORA-01591錯誤解決
<b> Tips:</b><b></b>
④ 本篇BLOG中指令的輸出部分需要特别關注的地方我都用灰色背景和粉紅色字型來表示,比如下邊的例子中,thread 1的最大歸檔日志号為33,thread 2的最大歸檔日志号為43是需要特别關注的地方;而指令一般使用黃色背景和紅色字型标注;對代碼或代碼輸出部分的注釋一般采用藍色字型表示。
List of Archived Logs in backup set 11
Thrd Seq Low SCN Low Time Next SCN Next Time
---- ------- ---------- ------------------- ---------- ---------
1 32 1621589 2015-05-29 11:09:52 1625242 2015-05-29 11:15:48
1 33 1625242 2015-05-29 11:15:48 1625293 2015-05-29 11:15:58
2 42 1613951 2015-05-29 10:41:18 1625245 2015-05-29 11:15:49
2 43 1625245 2015-05-29 11:15:49 1625253 2015-05-29 11:15:53
[ZHLHRDB1:root]:/>lsvg -o
T_XDESK_APP1_vg
rootvg
[ZHLHRDB1:root]:/>
00:27:22 SQL> alter tablespace idxtbs read write;
====》2097152*512/1024/1024/1024=1G
<b>本文如有錯誤或不完善的地方請大家多多指正,ITPUB留言或QQ皆可,您的批評指正是我寫作的最大動力。</b><b></b>
<b>項目</b><b></b>
<b>source db</b><b></b>
db 類型
RAC
db version
11.2.0.3
db 存儲
ASM
OS版本及kernel版本
AIX 64位 6.1.0.0
有同僚發來錯誤:
執行一個update語句的時候報錯ORA-01591的錯誤。
這個錯誤是由于分布式事務引起,而不是普通的鎖引起的,檢查一般對象資料表鎖定,隻需要檢查v$locked_object和v$transaction視圖,就可以定位到具體的SQL語句和操作人等資訊,但是檢查之後的結果如下:
SYS@oraLHR12> select * from gv$locked_object;
no rows selected
SYS@oraLHR12> select * from gv$transaction;
兩個關鍵視圖中,沒有鎖定的對象,也沒有正在進行沒有送出的事務。那是不是沒有鎖定呢?或者鎖已經釋放了,我們嘗試對資料表加鎖:
SYS@oraLHR12> select * from LHR.LHRBOKBAL for update;
select * from LHR.LHRBOKBAL for update
*
ERROR at line 1:
ORA-01591: lock held by in-doubt distributed transaction 20.13.14721
SYS@oraLHR12> select count(1) from LHR.LHRBOKBAL;
COUNT(1)
----------
30998411
系統沒有像一般阻塞那樣等待,而是報錯ORA-01591的錯誤,并且提示鎖被一個分布式事務持有,不能實作加鎖操作,那麼ORA-01591錯誤究竟是什麼呢?我們使用oerr工具檢視該錯誤編号,看看有沒有值得關注的資訊。
root@ZFLHRRSP:/# oerr ora 1591
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.
簡單的說,01591錯誤的原因是該對象被一個處在“in-doubt”狀态的分布式事務鎖定。分布式事務使用的是“two-phase commit”二階段送出技術。解決該問題的方法就是檢視内部表pending_trans$,确定分布式事務資訊。這種狀态的事務主要是由于在進行分布式事務時候,發生網絡突發中斷的情況,引起分布式事務無法正常結束,等待中斷節點的事務響應。于是,各節點的事務所鎖定的表就不會被釋放掉。
此時,我們檢查視圖DBA_2PC_PENDING(或者基表pending_trans$),檢視是否存在這種情況。
果然,目前存在一個阻塞分布式事務,處在prepared狀态。目前問題,主要是源于在進入prepared階段之後,發生了網絡中斷的現象,引起commit的階段不能等待到事務資訊。是以,才會一直處在Prepared狀态,資料表也就不會進行釋放。
對于這個事務,隻能通過連接配接網絡或者強制送出回退事務來結束。我們可以使用commit force或者rollback force來進行處理,這裡我們進行復原操作:
SYS@oraLHR12> rollback force '20.13.14721';
Rollback complete.
SYS@oraLHR12>
Rollback force的參數是DBA_2PC_PENDING中記錄本地事務資訊的編号即LOCAL_TRAN_ID。
此時,再次檢視資料。
此時,該事務狀态已經變化為forced rollback表示已經強制回退,我們再次嘗試鎖定表操作:
16:25:31 SQL> select CURRENCY from tpcc.TPCCBOKBAL WHERE ROWNUM=1 for update;
CURRENCY
--------
001
Executed in 0.025 seconds
可以看出已經不報錯了,可以正常執行。
分布式事務,簡單來說,是指一個事務在本地和遠端執行,本地需要等待确認遠端的事務結束後,進行下一步本地的操作。如通過dblink update遠端資料庫的一行記錄,如果在執行過程中網絡異常,或者其他事件導緻本地資料庫無法得知遠端資料庫的執行情況,此時就會發生in doublt的報錯。此時需要dba介入,且需要分多種情況進行處理。
Oracle會自動處理分布事務,保證分布事務的一緻性,所有站點全部送出或全部復原。一般情況下,處理過程在很短的時間内完成,根本無法察覺到。
但是,如果在commit或rollback的時候,出現了連接配接中斷或某個資料庫 站點CRASH的情況,則送出操作可能會無法繼續,此時DBA_2PC_PENDING和DBA_2PC_NEIGHBORS中會包含尚未解決的分布事務。 對于絕大多數情況,當恢複連接配接或CRASH的資料庫重新啟動後,會自動解決分布式事務,不需要人工幹預。隻有分布事務鎖住的對象急需被通路,鎖住的復原段阻止了其他事務的使用,網絡故障或CRASH的資料庫的恢複需要很長的時間等情況出現時,才使用人工操作的方式來維護分布式事務。 手工強制送出或復原将失去二層送出的特性,Oracle無法繼續保證事務的一緻性,事務的一緻性應由手工操作者保證
使用ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY,可以使Oracle不再自動解決分布事務,即使網絡恢複連接配接或者CRASH的資料庫重新啟動。
ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY恢複自動解決分布事務。
DBA_2PC_PENDING:列出所有的懸而未決的事務﹐此視圖在末填入懸而未決的事務之前是空的﹐解決這後也被清空。
<b>列名</b><b></b>
<b>說明</b><b></b>
LOCAL_TRAN_ID
本地事務辨別﹐格式為integer.integer.ingeger。
當一個連接配接的local_tran_id和global_tran_id相同時﹐那麼該節點是該事務的全局協調器。
GLOBAL_TRAN_ID
全局事務辨別,格式為﹕global_db_name.db_hex_id.local_tran_id,其中db_hex_id是用來辨別資料庫八字元的十六進制數﹐公共事各id在分布式事務的每個節點都是相同的。
STATE
下圖表進行說明
MIXED
“YES”意味着一部分事務已經在一個節點上送出﹐而在另一個節點上被復原。
TRAN_COMMENT
事務的注釋﹐或者如果使用了事務命名﹐當事各被送出時﹐事務的名字就會出現在此處
Host
主機名
Commit#
已送出的事務的全局送出數
DBA_2PC_PENDING的STATE列的說明
<b>列值</b><b></b>
Connecting
通常情況下﹐隻有全局協調器和本地協調器才使用這個條目﹐節點在能夠決定它是否能夠準備好之前﹐要收集來自于其它資料庫服務的資訊。
Prepared
節點已準好﹐可能或者也可能沒有将已準備好的消息通知本地協調器﹐但此時﹐該節點還沒有接收到送出的請求﹐仍保持着準許備好的狀态﹐控制着送出事務所必需的任何本地資源。
Commited
節點(任何類型)已經送出了事務﹐但該事務所包含的其它節點可能并沒有送出﹐也就是該事務在一個個或多個其它節點上仍然是懸而未決 。
Forced commit
DBA進行判斷後﹐可以強行送出未決的事務﹐如果一個事務由DBA在本地節點進行手動送出時﹐産生此項目
Forced abor(rollback)
DBA進行判斷後﹐可以強行復原未決的事務﹐如果一個事務由DBA在本地節點進行手動復原時﹐産生此項目
SELECT <b>*</b> FROM DBA_2PC_PENDING<b>;</b>
DBA_2PC_NEIGHBORS:列出所有獲得的(從遠端客戶)和送出的(給遠端伺服器)懸而未決的事務﹐也表示該本地節點是不是事務的送出點站點。
同上
IN_OUT
獲得事務為IN﹐送出事務為OUT
Database
對獲得事務來說指本地節點資訊的客戶資料庫的名稱﹔對送出的事務來說指用于通路遠端伺服器上資訊的資料庫連結的名稱
DBuser_owner
對獲得事務來說指遠端資料庫連結用于連接配接的本地賬戶﹔對于送出事務來說指該資料庫連結的擁有者。
INTERFACE
‘C’代表送出資訊﹐’N’表示已準備好狀态的一條消息或是一條請求隻讀送出的請求。
當’IN_OUT’為OUT時﹐’C’表示該連接配接的遠端的站點是送出點站點,并且知道是送出還是中斷。’N’表示本地節點正在通知遠端節點﹐說它已準備好。
當’IN_OUT’為IN時﹐‘C’表示本地節點或送出的遠端的一個資料庫是送出點站點﹐’N’表示本地節點正在通知遠端節點﹐說它已準備好。
About Me ............................................................................................................................... ● 本文作者:小麥苗,隻專注于資料庫的技術,更注重技術的運用 ● QQ群:230161599 微信群:私聊 ● 聯系我請加QQ好友(646634621),注明添加緣由 ● 于 2016-08-02 09:00~2016-08-03 19:00 在魔都完成 ● 文章内容來源于小麥苗的學習筆記,部分整理自網絡,若有侵權或不當之處還請諒解 ● 版權所有,歡迎分享本文,轉載請保留出處 拿起手機使用微信用戶端掃描下邊的左邊圖檔來關注小麥苗的微信公衆号:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。 <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=646634621&site=qq&menu=yes"></a>