【茶包射手日記】程式當掉時Oracle Transaction未自動Rollback

同事報案,稍早發生Oracle錯誤導致有一批排程作業失敗,很快找到錯誤,修正後重新執行排程卻出現更新資料庫發生Timeout,而Oracle錯誤後才新増的項目則可順利執行無誤。

由以上線索,推測最可能的原因是「出問題的資料被鎖定了」。檢查程式碼,啟動Transaction但未使用try…catch主動於出錯時Rollback。依據過去經驗,Oracle的Transaction在Client Process意外結束後不會自動Rollback,過程產生的資料鎖定也一直留在特定資料上,如此即能解釋為何出錯的一批資料重新執行會Timeout(苦等不到鎖定釋放)而事後新増的項目卻沒問題。經驗裡SQL Server在Client Process不正常結束時會自動Rollback Transaction,而Oracle未Commit的Transaction則會持殘留,需要人為介入處理。請DBA查詢,證實Oracle殘留未結束Session及Lock,砍掉Session後再重跑排程,Timeout問題消失。

找到Stackoverflow一則討論有相關說明:

未Commit或Rollback的Oracle Transaction會導致無法登出,因此當Client端當掉或異常中止,可能會留下Session及鎖定,需由DBA手動刪除。查詢Sesion及鎖定可使用以下SQL語法:

SELECT ses.sid, ses.serial#, ses.username, ses.program, ses.osuser, ses.machine
  FROM v$session ses,
       dba_blockers blk
 WHERE blk.holding_session = ses.sid

確認為異常Session後可使用以下指令刪除:

ALTER SYSTEM KILL SESSION '<<sid>>, <<serial#>>'

若想免除人為介入,Oracle有個Dead Connection Detection (DCD) 機制,定期偵測Client端是否還活著,主動砍掉Client掛點的無主Session。不過,最根本解決這個問題的做法是改良程式,使用 try … catch 區塊攔截錯誤,出錯時主動Rollback Transaction,比依賴第三方機制擦屁股更可靠更有效率。

歡迎推文分享:
Published 06 July 2016 06:36 AM 由 Jeffrey
Filed under:
Views: 3,407



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<July 2016>
SunMonTueWedThuFriSat
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication