DBMS_LOCK包¶
包DBMS_LOCK为用户提供了与锁相关的接口,从而使得PL程序具有了控制并发的能力。通过DBMS_LOCK提供的接口,可以进行请求特定模式的锁、更改锁定模式或者释放锁等操作。
包DBMS_LOCK提供与Oracle兼容的应用程序接口。
下表展示了DBMS_LOCK包的子程序。
| 子程序 | 描述 | 过程/函数 |
|---|---|---|
| ALLOCATE_UNIQUE | 为锁分配唯一的锁标识 | 过程 |
| REQUEST | 请求特定模式的锁 | 函数 |
| CONVERT | 将锁转换为特定的模式 | 函数 |
| RELEASE | 释放一个锁 | 函数 |
| SLEEP | 使程序休眠一定的时间 | 过程 |
以下内容介绍了DBMS_LOCK包中各种函数和过程的语法、参数和说明。
下表展示了DBMS_LOCK支持的锁模式和取值,以及各个锁模式之间的兼容性。
| 已授予锁 | 请求NL锁 | 请求SS锁 | 请求SX锁 | 请求S锁 | 请求SSX锁 | 请求X锁 |
|---|---|---|---|---|---|---|
| NL(1) | 成功 | 成功 | 成功 | 成功 | 成功 | 成功 |
| SS(2) | 成功 | 成功 | 成功 | 成功 | 成功 | 失败 |
| SX(3) | 成功 | 成功 | 成功 | 失败 | 失败 | 失败 |
| S(4) | 成功 | 成功 | 失败 | 成功 | 失败 | 失败 |
| SSX(5) | 成功 | 成功 | 失败 | 失败 | 失败 | 失败 |
| X(6) | 成功 | 失败 | 失败 | 失败 | 失败 | 失败 |
示例:DBMS_LOCK包¶
drop table t_lock;
create table t_lock(id int);
-- 加锁
create or replace function u_lock(LockName VARCHAR2(64), LockMode INTEGER, TimeOut INTEGER, bCommitOnRelease BOOLEAN) return number as
lockhandle VARCHAR2(100);
status INTEGER;
begin
dbms_lock.allocate_unique(LockName, lockhandle, 30);
status := dbms_lock.request(lockhandle,
LockMode, --锁定模式
TimeOut, --最多等待时间
bCommitOnRelease); -- 事务提交放锁
return status;
end;
/
-- 放锁
create or replace function u_release(LockName VARCHAR2(64)) return number as
lockhandle VARCHAR2(100);
status INTEGER;
begin
dbms_lock.allocate_unique(LockName, lockhandle, 30);
status := dbms_lock.release(lockhandle);
return status;
end;
/
-- 多个session并发执行下面的脚本,不会出现重复数据
DECLARE
v_result NUMBER;
v_rand NUMBER;
v_count NUMBER;
BEGIN
FOR i IN 1 .. 10000 LOOP
-- 获取0-10000之间的随机整数
select floor(rand()*(10000)) into v_rand;
v_result:= u_lock('lock_test', DBMS_LOCK.X_MODE, 1, FALSE);
IF v_result = 0 THEN
select count(*) into v_count from t_lock where id = v_rand;
IF v_count = 0 THEN
insert into t_lock values(v_rand);
-- dbms_output.put_line(v_rand);
END IF;
END IF;
v_result:= u_release('lock_test');
END LOOP;
END;
/
-- 查询是否有重复数据
select count(*) from t_lock group by t_lock.id having (count(*)) > 1;
COUNT(int) |
总数目:0
drop table t_lock;