DBMS_LOCK
提供多种锁模式,各模式都有自己的冲突列表。
各个锁模式的含义及取值如下表:
名字 |
描述 |
值 |
nl_mode |
NULL |
1 |
ss_mode |
Sub Shared,表示在一个对象的子部分上获取共享锁 |
2 |
sx_mode |
Sub Exclusive,表示在一个对象的子部分上获取独占锁 |
3 |
S_mode |
Shared,表示对整个对象获取共享锁 |
4 |
Ssx_mode |
Shared Sub Exclusive,表示整个对象已有共享锁,但是还要对某些字部份获取独占锁 |
5 |
X_mode |
Exclusive,表示对整个对象获取独占锁 |
6 |
- 当要获取一个对象的锁时,如果这个对象的锁正被其他会话所持有,那么需要根据该对象的锁正被持有的模式以及当前要获取的锁的模式来判断本次是否能够成功获取,不同锁模式的冲突列表如下:
HELD MODE |
GET NL |
GET SS |
GET SX |
GET S |
GET SSX |
GET X |
NL |
success |
success |
success |
success |
success |
success |
SS |
success |
success |
success |
success |
success |
fail |
SX |
success |
success |
success |
fail |
fail |
fail |
S |
success |
success |
fail |
success |
fail |
fail |
SSX |
success |
success |
fail |
fail |
fail |
fail |
X |
success |
fail |
fail |
fail |
fail |
fail |
函数名 |
参数类型 |
结果类型 |
描述 |
allocate_unique |
lockname varchar,OUT lockhandle varchar,expiration_secs integer |
varchar |
为指定的锁名分配一个唯一的锁id |
convert |
lockhandle varchar,id integer,lockmodeinteger,timeout integer |
integer |
用于进行锁模式的转换 |
request |
id integer,lockhandle varchar,lockmode integer,timeout integer,release_on_commit boolean |
integer |
请求一个指定模式的锁 |
release |
id integer,lockhandle varchar |
integer |
用来显示释放由request函数占有的锁 |
sleep |
seconds double precision |
null |
使session睡眠指定的时间 |
返回值 |
request函数输出返回值含义描述 |
release函数输出返回值含义 |
0 |
success |
success |
1 |
timeout |
|
2 |
deadlock |
|
3 |
parameter error |
parameter error |
4 |
already own lock specified by id or lockhandle |
don't own lock specified by lockhandle |
5 |
illegal lock handle |
illegal lock handle |
CREATE OR REPLACE FUNCTION lock_test() RETURNS int AS $$
DECLARE
v_ret int;
v_name varchar(100) := 'test';
v_handle varchar(100);
BEGIN
dbms_output.enable();
dbms_output.serveroutput(true);
dbms_output.put_line('----- session start ------');
select dbms_lock.allocate_unique(v_name, 2) into v_handle;
v_ret := dbms_lock.request(v_handle, 6, 100, false);
IF v_ret <> 0 THEN
-- 获取锁失败
dbms_output.put_line('--- lock request lock failed ---');
RETURN v_ret;
ELSE
dbms_output.put_line('--- now reqeust lock success ---');
END IF;
-- 获取锁成功,此处添加请求业务逻辑
dbms_lock.sleep(30);
-- 执行完成,应该要释放掉锁
IF v_ret = 0 THEN
v_ret := dbms_lock.release(v_handle);
END IF;
RETURN v_ret;
END;
$$ LANGUAGE plpgsql;