dbms_lock包的研究

先看一下各個包的接口與功能

--創建或得到同名鎖的句柄信息
DBMS_LOCK.ALLOCATE_UNIQUE (
lockname IN VARCHAR2,    --想要獲得的鎖名稱
lockhandle OUT VARCHAR2, --返回的鎖句柄信息
expiration_secs IN INTEGER DEFAULT 864000); --距離最後一次分配多久後自動釋放該鎖



對鎖的類型進行轉換
DBMS_LOCK.CONVERT(
id IN INTEGER ||
lockhandle IN VARCHAR2,  --鎖ID或鎖句柄
lockmode IN INTEGER,     --新的鎖模式
timeout IN NUMBER DEFAULT MAXWAIT)  --如果在指定的時間內得不到鎖,則返回1 請求(超時)
RETURN INTEGER;

通過鎖ID或句柄釋放鎖
DBMS_LOCK.RELEASE (
id IN INTEGER)
RETURN INTEGER;


DBMS_LOCK.RELEASE (
lockhandle IN VARCHAR2)
RETURN INTEGER;

拿到句柄申請鎖
DBMS_LOCK.REQUEST(
id IN INTEGER ||
lockhandle IN VARCHAR2,
lockmode IN INTEGER DEFAULT X_MODE,
timeout IN INTEGER DEFAULT MAXWAIT,
release_on_commit IN BOOLEAN DEFAULT FALSE)
RETURN INTEGER;
休眠
DBMS_LOCK.SLEEP (
seconds IN NUMBER);  休眠時長(秒)




實驗:

Session 1

DECLARE

  V_LOCK_HOLDER VARCHAR2(128);
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE('test_lockname', V_LOCK_HOLDER, 3600);

  DBMS_OUTPUT.PUT_LINE(V_LOCK_HOLDER);

END;

#######################################################################################
10737418641073741864187


session2 

DECLARE

  V_LOCK_HOLDER VARCHAR2(128);
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE('test_lockname', V_LOCK_HOLDER, 3600);

  DBMS_OUTPUT.PUT_LINE(V_LOCK_HOLDER);

END;

#######################################################################################
10737418641073741864187

點評:
先創建一個名字爲test_lockname的鎖  
返回這個鎖的引用句柄 得到這個句柄的會話可以對鎖進行申請,轉換,釋放。
如果這個鎖已經存在 則並不會報錯 同樣返回這個鎖的句柄。
但是擁有句柄並不代表你可以使用這個鎖的資源,只不過是擁有申請的權利而已.
就好比你知道一個人的電話號碼,你可以打,但是能不能打通就不一定了。
然後再使用dbms_lock.REQUEST的這個過程 來申請鎖 申請到了才能用.

session 1

DECLARE
v_result NUMBER ;
BEGIN
   
  v_result:= DBMS_LOCK.REQUEST('10737418641073741864187' ,DBMS_LOCK.X_MODE, 10, FALSE);
  dbms_output.put_line(v_result);
END;
#######################################################################################
0


session 2

DECLARE
v_result NUMBER ;
BEGIN
  dbms_output.put_line(to_char(SYSDATE,'hh24:mi:ss'));
  v_result:= DBMS_LOCK.REQUEST('10737418641073741864187' ,DBMS_LOCK.X_MODE, 10, FALSE);
  dbms_output.put_line(v_result);
  dbms_output.put_line(to_char(SYSDATE,'hh24:mi:ss'));
END;
#######################################################################################
14:07:58
1
14:08:08


session 1

DECLARE
v_result NUMBER ;
BEGIN
   
  v_result:= DBMS_LOCK.REQUEST('10737418641073741864187' ,DBMS_LOCK.X_MODE, 10, FALSE);
  dbms_output.put_line(v_result);
END;
#######################################################################################
4

點評 :

當我們使用seesion1 第一次申請 很快就申請到了
當我們使用seesion2 申請並指定可以重試10秒時 一直到10秒之後才返回1 沒有申請到
當我們再是使用session1 申請時 返回值就會變成4 表示該會話已經擁有該鎖。
DBMS_LOCK.REQUEST的對應值列表如下:

0 Success
1 Timeout
2 Deadlock
3 Parameter error
4 Already own lock specified by id or lockhandle
5 Illegal lock handle


session 3

DECLARE
v_result NUMBER ;
BEGIN 
  v_result:=DBMS_LOCK.RELEASE('10737418641073741864187' );
dbms_output.put_line(v_result) ;
END ;  
#######################################################################################
4

Session1 

DECLARE
v_result NUMBER ;
BEGIN 
  v_result:=DBMS_LOCK.RELEASE('10737418641073741864187' );
dbms_output.put_line(v_result) ;
END ; 
#######################################################################################
0
  
seesion2

DECLARE
v_result NUMBER ;
BEGIN
  dbms_output.put_line(to_char(SYSDATE,'hh24:mi:ss'));
  v_result:= DBMS_LOCK.REQUEST('10737418641073741864187' ,DBMS_LOCK.X_MODE, 10, FALSE);
  dbms_output.put_line(v_result);
  dbms_output.put_line(to_char(SYSDATE,'hh24:mi:ss'));
END;

#######################################################################################
14:26:45
0
14:26:45


點評
session3  試圖釋放一個由session1持有的鎖 但是沒有成功。返回值爲4
session1 對自己持有的鎖進行釋放,成功 返回0
此時seesion2再去申請該鎖,則很塊得到。


DBMS_LOCK.RELEASE
0 Success
3 Parameter error
4 Do not own lock specified by id or lockhandle
5 Illegal lock handle

還有一個轉換方法,也是需要所的持有者去做的,對應返回值列表

0 Success
1 Timeout
2 Deadlock
3 Parameter error
4 Don't own lock specified by id or lockhandle
5 Illegal lock handle


總結:
雖然Oracle的dbms_lock包提供了一套完整的鎖轉換機制。但是這個鎖本身只是一個信號量。
並沒有任何一個數據庫對象因爲該鎖的存在而被鎖定。
一般的應用還只是侷限於保證某些程序的串行化。

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