最近碰到比較頭痛的事情,原來單域部署的的應用變成了集羣部署,這樣java中鎖(lock)就失去了效應,因爲變成了多實例,於是實現過程採用存儲過程來封裝業務邏輯,但是之前沒有針對於存儲過程加鎖的經歷。
經過翻閱Oracle資料,發現Oralce可以針對存儲過程上鎖,保證業務邏輯單次通過,已測試驗證,特分享下。
在存過的代碼里加入下列代碼:
DBMS_LOCK.allocate_unique ('Lock', lockhandle);--針對當前session加鎖
LOOP
LN := DBMS_LOCK.request (lockhandle, TIMEOUT => 0);
IF LN NOT IN (0, 4)--判斷是否被別session鎖住
THEN
DBMS_OUTPUT.put_line ('Already run...');
DBMS_LOCK.sleep (2);--已經被人鎖住,休眠2秒
ELSE
EXIT;--沒有鎖,退出輪詢
END IF;
END LOOP;
--你要鎖住的業務邏輯代碼
LN := DBMS_LOCK.release (lockhandle);--釋放資源
測試方法,啓動線程1,在業務邏輯處打斷點,鎖住存過,啓動線程2執行存過,發現已經卡死;繼續執行線程1存過指導解鎖,發現線程2鎖死情況等待2秒後解除,爲了達到更好的效果,可以設置休眠時間更長一些
附:
DBMS_LOCK.request 返回值
0 申請鎖定成功
1 申請鎖定時超時
2 申請鎖定時發生死鎖
3 傳入參數錯誤
4 已經獲得了鎖定,重複申請了鎖
5 傳入的鎖定句柄錯誤
DBMS_LOCK.release 返回值
0 釋放鎖定成功
3 傳入參數錯誤
4 並沒有獲得要釋放的鎖定
5 傳入的鎖定句柄錯誤