在存储过程中调用dbms_包的权限问题

本文解决了一个关于Oracle数据库中使用DBMS_LOCK包的权限问题。具体表现为在匿名程序块中可以正常调用DBMS_LOCK.sleep过程,但在存储过程中却因未授权而失败。通过授予执行权限解决了该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

遇到一个问题,如下:
ETL@RACTEST> begin
  2  DBMS_LOCK.sleep(1);
  3  end;
  4  /

PL/SQL procedure successfully completed.

但是
ETL@RACTEST> CREATE OR REPLACE PROCEDURE etl.pliutest
  2  authid current_user
  3  AS
  4  BEGIN
  5     DBMS_LOCK.sleep(1);
  6  END;
  7  /


Warning: Procedure created with compilation errors.

Elapsed: 00:00:00.07
ETL@RACTEST> ETL@RACTEST> show errors
Errors for PROCEDURE ETL.PLIUTEST:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/2      PL/SQL: Statement ignored
5/2      PLS-00201: identifier 'DBMS_LOCK' must be declared

同一个包,在相同的用户下的匿名程序块中可以执行,但是在存储过程中却没有权限执行,查了下资料,一些DBMS_开头的pkg在pl/sql中用到的时候,需要显示的执行
grant execute on dbms_xxxx to xxx 来赋下权限才可以。此外这个授权system用户是没有权限的,要sys 或者plsql / as dba登录才有权限授权。
授权以后可以看到:
SYSTEM@RACTEST> select grantee,owner,table_name,grantor,privilege from dba_tab_privs where table_name like 'DBMS_LOCK';

GRANTEE                                  OWNER      TABLE_NAME       GRANTOR     PRIVILEGE
--------------------                    ----------           ----------            ----------           ----------
EXECUTE_CATALOG_ROLE                       SYS              DBMS_LOCK          SYS             EXECUTE
DMSYS                                    SYS               DBMS_LOCK         SYS             EXECUTE
CTXSYS                                   SYS               DBMS_LOCK         SYS             EXECUTE
EXFSYS                                   SYS               DBMS_LOCK         SYS             EXECUTE
MDSYS                                    SYS               DBMS_LOCK         SYS             EXECUTE
OLAPSYS                                SYS                DBMS_LOCK        SYS             EXECUTE
SYSMAN                                  SYS               DBMS_LOCK         SYS             EXECUTE
ETL                                         SYS               DBMS_LOCK         SYS             EXECUTE

8 rows selected.

然后再次执行:
SYSTEM@RACTEST> CREATE OR REPLACE PROCEDURE etl.pliutest
  2  authid current_user
  3  AS
  4  BEGIN
  5     DBMS_LOCK.sleep(1);
  6  END;
  7  /


Procedure created.

OK了!

 转自:http://blog.sina.com.cn/s/blog_6ff05a2c0100mico.html

<think>好的,我现在需要帮用户介绍存储过程中使用DBMS_LOCK.SLEEP的情况。首先,我得确认用户对Oracle数据库的存储过程有基本了解,可能他们需要暂停或延迟执行流程。DBMS_LOCK.SLEEP这个可能用于这个目的。 接下来,我需要回想一下DBMS_LOCK.SLEEP的具体用法。记得这个函数属于DBMS_LOCK,参数是秒数,可以让会话暂停一段时间。但可能需要注意权限问题,比如用户是否有执行这个权限,可能需要授权。 然后,用户可能想知道为什么用这个而不是其他方法,比如Java的sleep或者应用层的等待。这时候需要比较不同方法的适用场景,比如在数据库层面直接控制延迟可能更直接,但也会占用数据库连接资源,影响性能。 还要考虑使用场景,比如模拟长时间操作、测试并发控制、或者定时任务中的间隔执行。同时,需要注意长时间睡眠可能导致会话挂起,消耗资源,甚至引发锁的问题,尤其是在高并发环境下。 另外,可能提到替代方案,比如DBMS_SESSION.SLEEP,但不同版本可能有不同,需要确认Oracle版本兼容性。还要提醒用户谨慎使用,避免在生产环境中滥用,导致性能问题。 最后,总结使用时的注意事项,比如合理设置时间、权限管理、资源消耗评估,以及可能的替代方案。确保用户理解正确使用场景和潜在风险。</think>在Oracle数据库中使用`DBMS_LOCK.SLEEP`的注意事项和典型场景如下: ### 基本语法 ```sql DBMS_LOCK.SLEEP(seconds IN NUMBER); ``` 参数单位为秒,支持小数(如`0.5`表示500毫秒) ### 核心用途 1. **模拟耗时操作** ```sql BEGIN DBMS_OUTPUT.PUT_LINE('开始操作'); DBMS_LOCK.SLEEP(5); -- 暂停5秒 DBMS_OUTPUT.PUT_LINE('5秒后继续'); END; ``` 2. **并发控制测试** 测试锁竞争时制造人为延迟: ```sql CREATE OR REPLACE PROCEDURE concurrent_test IS BEGIN LOCK TABLE orders IN EXCLUSIVE MODE; DBMS_LOCK.SLEEP(10); -- 持有锁10秒 END; ``` 3. **定时任务调度** 简单轮询场景(生产环境建议改用DBMS_SCHEDULER): ```sql LOOP -- 检查条件 IF condition_not_met THEN DBMS_LOCK.SLEEP(60); -- 每分钟检查一次 END IF; END LOOP; ``` ### 关键注意事项 1. **权限要求** 需要显式授权(DBA执行): ```sql GRANT EXECUTE ON DBMS_LOCK TO your_user; ``` 2. **版本兼容性** - Oracle 11g及更早版本:只能使用`DBMS_LOCK.SLEEP` - Oracle 18c+:推荐使用`DBMS_SESSION.SLEEP`(语法相同) 3. **性能影响** 执行期间会保持: - 数据库连接 - 事务锁(如果处于事务中) - PGA内存资源 ### 替代方案对比 | 方法 | 精度 | 是否释放连接 | 适用场景 | |----------------------|--------|------------|---------------------| | DBMS_LOCK.SLEEP | 秒级 | 否 | 短时间阻塞 | | DBMS_SESSION.SLEEP | 微秒级 | 否 | 高精度等待(18c+) | | JAVA调用Thread.sleep | 毫秒级 | 是 | 应用层延迟 | ### 典型错误示例 ```sql BEGIN FOR i IN 1..100 LOOP DBMS_LOCK.SLEEP(1); -- 避免在循环中高频使用 UPDATE logs SET count = count + 1; END LOOP; COMMIT; END; ``` **问题分析**: - 每个循环迭代产生1秒延迟 - 持续持有未提交的事务锁 - 总执行时间超过100秒,容易导致锁竞争和资源浪费 建议改用`DBMS_JOB`/`DBMS_SCHEDULER`实现定时任务调度,而非在代码中硬编码延迟逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值