設置事務超時時間的問題及Oracle數據庫update和鎖

寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有需要學習的朋友可以Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

Oracle的update語句問題:

update config t set t.value =1 where t.key='DB_ KEY'

或者:

select * from config t where t.key='DB_KEY' for update

這個update會試圖爲where條件指定的那些數據加上行級鎖,但如果此時這些數據已經被其他事務加鎖了,則會一直等待,直到鎖被釋放,然後再去競爭這些數據的鎖。

問題是,我不想讓它一直等待,如果加不上鎖就立即返回失敗信息。對於select ... for update語句,可以用如下方式:

select ... for update nowait(加鎖失敗則立即報錯)
select ... for update wait 3(最多等待3秒)

但僅限於select ... for update語句,update語句沒有這個功能。而且,這是Oracle數據庫所特有的功能。

我在設計多服務器、多線程數據庫同步操作時,最開始是採用的如下方式:

// 如果更新成功了,則i=1,否則i=0
int i = "update config t set t.flag =1 where t.key='DB_KEY' and t.flag=0"; 
// 當i=1時才允許去做查詢和更新數據
if(i==1) do query & update DATA; 
// 查詢完之後將DB_KEY的flag改回原來的值
update config t set t.flag =0 where t.key='DB_KEY' and t.flag=1

從中可見,t.key='DB_KEY'這條數據就好似一把鎖,誰成功的將flag置爲1就意味着誰打開了這把鎖,只有打開了鎖才能操作真正的數據,避免了多服務器、多線程查詢出同樣的數據。

但是啊,上面的方法有個致命的缺點:如果一個線程將鎖打開了,而因爲意外死亡(停機、重啓等原因)未能將鎖鎖上,那麼這意味着什麼?意味着這把鎖永遠處於打開狀態,其他線程都沒有機會再次獲取它了。所以我想到了利用事務來控制,起初開啓事務,然後再update KEY,如果成功了,再query & update DATA,然後再update KEY歸還鑰匙。如果線程意外停止了,那麼未提交的事務會立即回滾,鎖迴歸未使用狀態。

我是這樣做的,設置事務的超時時間:開啓事務——update——doSomething比如query——關閉事務。事務超時時間設置爲5秒。如果update等待超過這個時間,則會拋出異常,報錯終止。

爲什麼要設置一個超時時間呢,因爲完整的這一套事務控制需要一定時間,比如4秒,如果DB_KEY已經被加鎖,則其他update KEY將會處於等待狀態,等待多久,這個時間是不可控的,所以我想要自己來控制這個等待的timeout時間。

但是我測試時發現的是,超時後,update處沒有報錯,後面的query依然執行,query時才報錯(事務超時異常)。這是個比較難看透的問題,我想了很久纔想通,原因是update時可能已經等待了4.99秒,然後update成功了,接着執行query,但是此時時間已經超過5秒了,所以query報事務超時異常(正所謂,好不容易等到update成功了,但是卻沒有足夠的時間留給後面的query)。因此,update和query的時間差不能太大,否則的話有可能update成功了而query失敗(從設計上講,我不太希望有這種情況出現,當然,即使出現了,也只是浪費了一次事務罷了)。

分析清楚了這個問題之後,現在有兩種合理的設計方案:

1)不用事務,直接走update KEY——query & update DATA——update KEY路線,但是在update KEY時要記錄update date,並啓動一個線程循環不斷的去檢查KEY是否處於flag=1且now - update date > 30秒的狀態,如果處於這種狀態,則佔用KEY的時間過長,因而斷定獲取KEY的那個線程出現了異常,沒有能力將KEY還原,此時這個Check線程就幫忙把KEY重置爲未使用狀態。

2)使用事務,爲update KEY——query & update DATA——update KEY期間加上事務控制,如果線程掛掉,則事務回滾。也可以設置一個超時時間,但是有可能會因爲timeout限制而誤殺正常的流程。因此超時時間不能太短——越短,誤殺正常流程的機率越大。

來源:https://blog.csdn.net/zollty/article/details/85165342

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章