Oracle DBMS_LOCK包探究

Posted by 道行尚浅 on July 14, 2015

先看一下各个包的接口与功能  
  
--创建或得到同名锁的句柄信息  
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包提供了一套完整的锁转换机制。但是这个锁本身只是一个信号量。  
并没有任何一个数据库对象因为该锁的存在而被锁定。  
一般的应用还只是局限于保证某些程序的串行化。