由JTA分散式事務Timeout值引發的鎖定及解決
宣告:本文思路解決受dbsnake老師指點,特此感謝!
分散式系統較傳統的單點系統,具有較強的可擴充性和可用性,是目前大型應用系統普遍採用的設計模式。但是較傳統系統,分散式系統無論從複雜性還是出現故障的機率看,都是遠遠超過單點系統。當我們選擇開發分散式系統的時候,就意味要傾注更多的精力。
1、分散式事務
分散式事務是分散式系統的一個重要研究範疇。在Oracle中,採用“二階段提交”(Two phases submit)作為分散式事務的處理模型。簡單的說,當一個事務涉及操作物件分佈在不同的資料庫上。傳統的鎖機制和事務模型都是建立在單例項資料庫基礎上的。分散式事務要保證各個節點上事務都成功的前提下,才能確定事務提交完成。只要有一個事務沒有完成,所有節點的事務都要進行rollback。
分散式事務一個最難處理的問題,就是通訊帶來的timeout取值。分散式事務要伴隨著大量的節點間通訊互動,確定其他工作節點是否事務是否完成。這種等待是很大的問題,因為節點不知道其他節點不響應是“因為節點已經死亡,還是節點網路繁忙”。所以timeout設定就是一個很大的問題。
這種問題的極端體現就是,一個事務中涉及到多個節點內容。當一個節點鎖住一些物件,開啟了事務過程,就不斷地等待其他節點的響應。而由於各種原因,沒有相應到來。這樣就需要進行事務回收問題。
通常情況下,Oracle是可以自動處理這種問題的。在一個分散式事務中,有三個層面的timeout引數解決分散式事務鎖。
ü 全域性事務timeout(Global Transaction Timeout):在這種方式下,Oracle是不負責分散式事務管理的。Oracle將事務管理權交付給應用處理,如JTA事務容器。這種方式的事務管理,完全取決於應用程式配置內容。比如在JDBC和JTA中,有專門的Time out引數;
ü Session Timeout:指定了一個事務可以持續的最長時間,超過了這個時間就會被自動回收中斷。一個XA事務與Oracle Process的關係是比較鬆散,可以進行detach操作。當一個分散式事務失敗的時候,Oracle可以透過時間設定情況,將XA事務detach from the process;
ü Oracle內部的distributed_lock_timeout限制住一個分散式事務可以鎖住物件的最長時間。該引數通常預設設定一個很大的取值;
上述的三個timeout中,大小配置順序通常是:global transaction timeout < session timeout < distributed_lock_timeout。
很多時候,配置過大的timeout值,可能會引起一些問題和物件鎖定。
2、“shadow session”現象
當我們使用JTA事務模型的時候,分散式事務管理權是從Oracle轉移到JTA框架來進行管理。但如果事務中出現JTA的異常終止,就可能出現分散式問題。檢查系統中,存在事務資訊。
--篇幅原因,結果列有刪減;
SQL> select * from v$transaction;
ADDR XIDUSN XIDSLOT XIDSQN UBAFIL
---------------- ---------- ---------- ---------- ----------
070000007B5AC368 1 6 42735 3
存在事務,該事務的標識是(1,6,42735)。此時存在被鎖定的物件。
SQL> select * from v$locked_object;
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME OS_USER_NAME LOCKED_MODE
---------- ---------- ---------- ---------- ---------- --------------------------------- -----------
1 6 42735 114245 181 SYSMAN 3
從v$lock_object中,可以看到當前事務鎖定object_id=114245的物件,會話編號為sid=181,鎖模式為共享鎖模式。注意:此時user顯示的是sysman的系統內建使用者。
此時物件是存在的,也能確定鎖物件確實存在。
SQL> select * from dba_objects where object_id=114245;
OWNER OBJECT_NAME
------------------------------ ------------
NBS_COMMON BAT_LOCK
SQL> select * from bat_lock for update nowait;
select * from bat_lock for update nowait
ORA-00054: 資源正忙, 但指定以 NOWAIT 方式獲取資源, 或者超時失效
下面進行sid=181檢查,發現該會話是不存在v$session中的。也找不到對應的共享鎖資訊。
SQL> select count(*) from v$session where sid=181;
COUNT(*)
----------
0
SQL> select * from v$lock where id1=114245;
ADDR KADDR SID TYPE
---------------- ---------------- ---------- ----
最為詭異的情況是v$locked_object中,oracle_username不斷的幻象讀。
SQL> select * from v$locked_object;
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME
---------- ---------- ---------- ---------- ---------- ------------------------------
8 12 48826 114245 181
SQL> select * from v$locked_object;
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME
---------- ---------- ---------- ---------- ---------- ------------------------------
8 12 48826 114245 181 NBS
沒有v$session資訊就無法進行session級別的kill操作。同時,使用OS級別的Server Process kill操作也沒有作用。Oracle始終不能對事務資源進行回收。
3、分析問題和解決
該現象產生的原因是JTA事務的timeout值設定過大造成的。在使用JTA事務模型中,存在一個事務timeout引數,預設值為5分鐘。如果使用JTA進行分散式事務,Oracle會將分散式事務的控制權交出,由JTA進行事務控制。
這就是我們在第一部分中說的Global Transaction Timeout取值。JTA Timeout變相定義了在使用JTA中,一個資料庫操作事務可以持續多長時間。如果超過這個時間,JTA會自動中斷正在執行的事務,並且進行回滾。這也就限制了一個事務的時間長短。
對OLTP系統來說,我們一般期望事務規模儘可能小且短,時間越快越好。從而保證併發性和可擴充性。對OLAP系統來說,就有所差別。一些SQL執行過程可能會較長。所以對不同系統設定不同的JTA Timeout值,是必要的。
JTA是會向Oracle搶奪事務控制權的。如果JTA在一個分散式事務進行中崩潰,那麼Oracle是不會對事務進行資源回收和鎖釋放的。
在我們的例子中,就是一個明顯的表現。Oracle只有經過JTA Timeout設定的時間,才可能會進行回收。
那麼,有沒有辦法在JTA失敗後,不經過Timeout時間進行回收呢?在MOS 1248848.1中,我們找到了Java程式碼XA_rb.java,執行這個類方法,就可以實現資源的回收。程式碼地址:http://space.itpub.net/17203031/viewspace-709216。
該程式的原理,就是使用Oracle JDBC實現中的類,對特定事務進行強制回收。作為引數,要輸入連線資料庫的URL地址,以及回收事務的標識。
++ URL: jdbc:oracle:thin:@10.1.15.64:1521:NBSDEV
++ Rollback of Local_tran_ID : 1.6.42735
++ got XA resource handle
++ got Connection handle
++ SQL : select g.K2GTIFMT, g.K2GTITID_EXT, g.K2GTIBID, rawtohex( g.K2GTITID_EXT), rawtohex(g.K2GTIBID) from sys.v_x$k2gte g, sys.v_x$ktcxb t, sys.v_x$ktuxe x where g.K2GTDXCB =t.KTCXBXBA and x.KTUXEUSN = t.KXIDUSN(+) and x.KTUXESLT = t.KXIDSLT(+) and x.KTUXESQN =t.KXIDSQN(+) and t.KXIDUSN=1 and t.kXIDSLT=6 and t.kXIDSQN= 42735
++ Getting XID for Local_Tran_ID: 1.6.42735
+ Found global XID: -->
++ Format Id: 1096044365
++ Group Id: 31302E312E362E3233392E746D30303030313031303435
++ Branch Id: 31302E312E362E3233392E746D31
-> Would your really like to continue (yes or no):
yes
... doing Rollback
... Rollback done !
此時,再進行檢查,可以發現事務被回收。
SQL> select * from v$locked_object;
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME
---------- ---------- ---------- ---------- ---------- ---------------------
SQL> select * from bat_lock for update nowait;
LOCK_NAME
------------------------------
TASK_ACCESS
SQL> rollback;
Rollback complete
4、結論
分散式事務較之傳統事務模型,複雜性和管理難度要遠遠大於傳統事務。Oracle內部支援分散式事務,有二階段提交模型。一些事務管理框架,也都存在相應的事務模型方法。
對分散式事務中存在的問題,需要重點關注。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-709661/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- etcd分散式鎖及事務分散式
- 微服務架構及分散式事務解決方案微服務架構分散式
- 分散式事務解決方案分散式
- 高併發架構系列:分散式鎖的由來、特點及Redis分散式鎖的實現詳解架構分散式Redis
- 分散式事務之JTA原理與實現(三)分散式
- 常用的分散式事務解決方案分散式
- 分散式事務以及解決方法分散式
- 關於分散式事務帶來的問題及解決方案分散式
- SpringCloud 分散式事務解決方案SpringGCCloud分散式
- MSSQL server分散式事務解決方案SQLServer分散式
- 分散式事務解決方案--GTS(二)分散式
- 分散式事務解決方案--GTS(一)分散式
- 分散式事務解決方案彙總分散式
- 搞懂分散式技術19:使用RocketMQ事務訊息解決分散式事務分散式MQ
- 分散式事務(2)---強一致性分散式事務解決方案分散式
- Spring的分散式事務實現(JTA+XA/2PC)Spring分散式
- 基於RocketMq的分散式事務解決方案MQ分散式
- 分散式鎖的解決方案分散式
- 分散式事務(一)—分散式事務的概念分散式
- 分散式事務解決方案(一)【介紹】分散式
- 你必須瞭解的分散式事務解決方案分散式
- 分散式鎖和spring事務管理分散式Spring
- 分散式訊息佇列RocketMQ--事務訊息--解決分散式事務的最佳實踐分散式佇列MQ
- 分散式事務的疑問,JTA,歡迎banq 大師不吝賜教分散式
- 用分散式鎖解決併發問題分散式
- 分散式事務解決方案(四)【最大努力通知】分散式
- 分散式事務解決方案(五)【TCC型方案】分散式
- 聊聊分散式事務,再說說解決方案分散式
- 分散式事務解決方案——柔性事務與服務模式分散式模式
- 微服務分散式事務4種解決方案實戰微服務分散式
- Redis分散式鎖引發的工作事故Redis分散式
- 分散式事務鎖模式之一:租用Lease分散式模式
- Redis分散式鎖解決方案Redis分散式
- Redis 分散式鎖解決方案Redis分散式
- .NET開源的處理分散式事務的解決方案分散式
- (16)mysql 中的表鎖定及事務控制MySql
- ORACLE分散式事務鎖各種場景下的處理詳解Oracle分散式
- 外賣訂單-分散式事務解決實錄分散式