#DBMS_LOCK

DBMS_LOCK包提供了一组内置的存储过程和函数,用于管理和控制用户锁资源,允许用户显式定义锁,实现对共享资源的并发控制。支持创建、获取、释放锁,以及设置锁的等待时间等,常用于协调多个会话或事务对临界资源的访问。

Note:

  • REQUEST和CONVERT函数目前只支持S_MODE和X_MODE两种锁模式。

  • 普通用户使用锁函数前需要先获取DBMS_LOCK包的执行权限。

  • 除SLEEP外,DBMS_LOCK高级包的其他子程序在单机主备部署或主备集群部署中,只能在主库/主集群上执行。

  • 除SLEEP外,DBMS_LOCK高级包的其他子程序不适用于存算一体分布式集群部署。

# 预定义常量

# 锁模式常量

常量名 类型 说明
NL_MODE NUMBER 1 空锁模式
SS_MODE NUMBER 2 行共享模式
SX_MODE NUMBER 3 行排他模式
S_MODE NUMBER 4 共享模式,允许其他会话读取但不允许修改
SSX_MODE NUMBER 5 共享排他模式
X_MODE NUMBER 6 排他模式,其他会话不能读取或修改

Note:

目前REQUEST和CONVERT函数只支持S_MODE(4)和X_MODE(6)两种模式,其他锁模式仅作兼容处理。

# 超时常量

常量名 类型 说明
MAXWAIT NUMBER 32767 最大等待时间(单位:秒),表示无限等待

# 锁模式转换规则

当前持有模式 请求S_MODE 请求X_MODE
S_MODE 成功 等待
X_MODE 等待 等待

# ALLOCATE_UNIQUE

DBMS_LOCK.ALLOCATE_UNIQUE(
    lockname         IN   VARCHAR,
    lockhandle       OUT  VARCHAR,
    expiration_secs  IN   NUMBER   DEFAULT 864000);

该子存储过程用于为指定的锁名称分配一个唯一的锁标识符LOCKID,锁标识符用于使应用程序能够协调使用锁。

参数 类型 描述
lockname VARCHAR 锁名称,用于分配唯一锁标识符,长度不超过128字符
lockhandle VARCHAR 返回锁标识符的句柄,在后续调用REQUEST、CONVERT和RELEASE时使用此句柄标识锁资源。所有会话使用相同锁名称的锁句柄都引用同一个锁
expiration_secs NUMBER 锁过期时间(单位:秒),在最后一次ALLOCATE_UNIQUE之后等待多少秒才允许删除该锁,默认值为864000(10天)

示例(单机/共享集群/分布式集群部署)

DECLARE
    lock_name   VARCHAR(200);
    lock_handle VARCHAR(200);
BEGIN
    lock_name := 'user_lock';
    DBMS_LOCK.ALLOCATE_UNIQUE(
        lockname         => lock_name,
        lockhandle       => lock_handle,
        expiration_secs  => 60);
    DBMS_OUTPUT.PUT_LINE('lockhandle: ' || lock_handle);
END;
/

# REQUEST

-- 方式一:使用锁ID
DBMS_LOCK.REQUEST(
    id                 IN  NUMBER,
    lockmode           IN  NUMBER  DEFAULT X_MODE,
    timeout            IN  NUMBER  DEFAULT MAXWAIT,
    release_on_commit  IN  BOOLEAN  DEFAULT FALSE)
RETURN NUMBER;

-- 方式二:使用锁句柄
DBMS_LOCK.REQUEST(
    lockhandle         IN  VARCHAR,
    lockmode           IN  NUMBER  DEFAULT X_MODE,
    timeout            IN  NUMBER  DEFAULT MAXWAIT,
    release_on_commit  IN  BOOLEAN  DEFAULT FALSE)
RETURN NUMBER;

该存储函数用于获取指定模式的锁。返回0表示执行成功,返回其他值则表示失败,具体原因取决于返回值:

  • 返回1表示超时。
  • 返回2表示死锁。
  • 返回3表示参数错误。
  • 返回4表示已经持有指定的锁。
  • 返回5表示非法的锁句柄。
参数 类型 描述
id NUMBER 用户自定义锁标识符,范围为0到1073741823,避免使用区间2000000000到2147483647
lockhandle VARCHAR 锁句柄,通过ALLOCATE_UNIQUE的出参lockhandle获取
lockmode NUMBER 需要获取的锁模式,仅支持S_MODE(4)和X_MODE(6)
timeout NUMBER 获取锁的尝试秒数,0表示非阻塞立即返回,32767(MAXWAIT)表示无限等待
release_on_commit BOOLEAN 是否在事务提交或回滚时释放锁。FALSE表示锁将保持持有直到显式释放或会话结束

示例(单机/共享集群/分布式集群部署)

-- 使用锁句柄请求X_MODE锁
DECLARE
    lock_name   VARCHAR(200);
    lock_handle VARCHAR(200);
    res         INTEGER;
BEGIN
    lock_name := 'user_lock';
    DBMS_LOCK.ALLOCATE_UNIQUE(lockname => lock_name, lockhandle => lock_handle);
    res := DBMS_LOCK.REQUEST(lock_handle, DBMS_LOCK.X_MODE, 60, FALSE);
    DBMS_OUTPUT.PUT_LINE('result: ' || res);
END;
/

-- 使用锁ID请求S_MODE锁
DECLARE
    res INTEGER;
BEGIN
    res := DBMS_LOCK.REQUEST(1, DBMS_LOCK.S_MODE, 60, FALSE);
    DBMS_OUTPUT.PUT_LINE('result: ' || res);
END;
/

# CONVERT

-- 方式一:使用锁ID
DBMS_LOCK.CONVERT(
    id        IN   NUMBER,
    lockmode  IN   NUMBER,
    timeout   IN   NUMBER   DEFAULT MAXWAIT)
RETURN NUMBER;

-- 方式二:使用锁句柄
DBMS_LOCK.CONVERT(
    lockhandle  IN   VARCHAR,
    lockmode    IN   NUMBER,
    timeout     IN   NUMBER   DEFAULT MAXWAIT)
RETURN NUMBER;

该存储函数用于将锁从一种模式转换成另一种模式。返回0表示执行成功,返回其他值则表示失败,具体原因取决于返回值:

  • 返回1表示超时。
  • 返回2表示死锁。
  • 返回3表示参数错误。
  • 返回4表示未持有指定的锁。
  • 返回5表示非法的锁句柄。
参数 类型 描述
id NUMBER 用户自定义锁标识符,范围为0到1073741823,避免使用区间2000000000到2147483647
lockhandle VARCHAR 锁句柄,通过ALLOCATE_UNIQUE的出参lockhandle获取
lockmode NUMBER 需要转换的目标锁模式,仅支持S_MODE(4)和X_MODE(6)之间的转换
timeout NUMBER 转换锁模式的尝试秒数,0表示非阻塞立即返回,32767表示无限等待

示例(单机/共享集群/分布式集群部署)

-- S_MODE转换为X_MODE
DECLARE
    lock_name   VARCHAR(200);
    lock_handle VARCHAR(200);
    res         INTEGER;
BEGIN
    lock_name := 'user_lock';
    DBMS_LOCK.ALLOCATE_UNIQUE(lockname => lock_name, lockhandle => lock_handle);
    res := DBMS_LOCK.REQUEST(lock_handle, DBMS_LOCK.S_MODE, 60, FALSE);
    DBMS_OUTPUT.PUT_LINE('request result: ' || res);
    res := DBMS_LOCK.CONVERT(lock_handle, DBMS_LOCK.X_MODE, 60);
    DBMS_OUTPUT.PUT_LINE('convert result: ' || res);
END;
/

# RELEASE

-- 方式一:使用锁ID
DBMS_LOCK.RELEASE(
    id  IN  NUMBER)
RETURN NUMBER;

-- 方式二:使用锁句柄
DBMS_LOCK.RELEASE(
    lockhandle  IN  VARCHAR)
RETURN NUMBER;

该存储函数用于显式释放先前使用REQUEST函数获取的锁。锁在会话结束时也会自动释放。返回0表示执行成功,返回其他值则表示失败,具体原因取决于返回值:

  • 返回3表示参数错误。
  • 返回4表示未持有指定的锁。
  • 返回5表示非法的锁句柄。
参数 类型 描述
id NUMBER 用户自定义锁标识符,范围为0到1073741823或2000000000到2147483647
lockhandle VARCHAR 锁句柄,通过ALLOCATE_UNIQUE的出参lockhandle获取

示例(单机/共享集群/分布式集群部署)

-- 使用锁句柄释放锁
DECLARE
    lock_name   VARCHAR(200);
    lock_handle VARCHAR(200);
    res         INTEGER;
BEGIN
    lock_name := 'user_lock';
    DBMS_LOCK.ALLOCATE_UNIQUE(lockname => lock_name, lockhandle => lock_handle);
    res := DBMS_LOCK.REQUEST(lock_handle, DBMS_LOCK.X_MODE, 60, FALSE);
    DBMS_OUTPUT.PUT_LINE('request result: ' || res);
    res := DBMS_LOCK.RELEASE(lock_handle);
    DBMS_OUTPUT.PUT_LINE('release result: ' || res);
END;
/

# SLEEP

DBMS_LOCK.SLEEP(
    second IN NUMBER);

该子存储过程用于将系统按参数指定的秒数进行休眠,单位为秒。

执行该子存储过程后,系统将按参数指定的秒数进行休眠。如需在秒数结束前停止休眠,须在终端执行CTRL+C、Shutdown等指令进行强制退出。

参数 类型 描述
second NUMBER 指定休眠的时间,不可输入空,数值范围必须为[0,21474836.47],支持入参类型隐式转换。

示例(单机/共享集群/分布式集群部署)

-- 数值型
EXEC DBMS_LOCK.SLEEP(10);

-- 字符串型
EXEC DBMS_LOCK.SLEEP('10');

-- BIT型
DECLARE
vsql VARCHAR(256);
vbit BIT(8);
BEGIN
vsql := 'exec DBMS_LOCK.SLEEP (?)';
vbit := 5;
EXECUTE IMMEDIATE vsql USING vbit;
END;
/

-- 布尔型
DECLARE
vsql VARCHAR(256);
vbool BOOLEAN;
BEGIN
vsql := 'exec DBMS_LOCK.SLEEP (?)';
vbool := 'true';
EXECUTE IMMEDIATE vsql USING vbool;
END;
/
edit-icon
反馈
coperate-icon
coperate
合作
communication-icon
communicate
交流