先看一下各个包的接口与功能
--创建或得到同名锁的句柄信息
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包提供了一套完整的锁转换机制。但是这个锁本身只是一个信号量。
并没有任何一个数据库对象因为该锁的存在而被锁定。
一般的应用还只是局限于保证某些程序的串行化。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24558043/viewspace-677908/,如需转载,请注明出处,否则将追究法律责任。