ORACLE中的睡眠功能
我需要在 ORACLE 中执行 SQL 查询,这需要一定的时间。 所以我写了这个函数:
CREATE OR REPLACE FUNCTION MYSCHEMA.TEST_SLEEP
(
TIME_ IN NUMBER
)
RETURN INTEGER IS
BEGIN
DBMS_LOCK.sleep(seconds => TIME_);
RETURN 1;
EXCEPTION
WHEN OTHERS THEN
RAISE;
RETURN 1;
END TEST_SLEEP;
我以这种方式调用,
SELECT TEST_SLEEP(10.5) FROM DUAL
但为了工作,我需要向过程的所有者设置DBMS_LOCK
的授予。
如何在不使用 DBMS_LOCK.sleep 函数的情况下重写此函数?
I need execute an SQL query in ORACLE it takes a certain amount of time.
So I wrote this function:
CREATE OR REPLACE FUNCTION MYSCHEMA.TEST_SLEEP
(
TIME_ IN NUMBER
)
RETURN INTEGER IS
BEGIN
DBMS_LOCK.sleep(seconds => TIME_);
RETURN 1;
EXCEPTION
WHEN OTHERS THEN
RAISE;
RETURN 1;
END TEST_SLEEP;
and I call in this way
SELECT TEST_SLEEP(10.5) FROM DUAL
but to work I need set grant of DBMS_LOCK
to the owner of the procedure.
How I can rewrite this function without using the DBMS_LOCK.sleep
function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
如果没有授予对 DBMS_LOCK.sleep 的访问权限,这会起作用,但这是一个可怕的黑客行为:
Short of granting access to
DBMS_LOCK.sleep
, this will work but it's a horrible hack:创建一个仅执行锁定操作的过程,并将其安装到另一个用户,该用户是 dbms_lock ( USERA )“信任”的用户,授予 USERA 对 dbms_lock 的访问权限。
然后只需授予 USERB 访问此功能的权限即可。然后,他们不需要能够访问 DBMS_LOCK
(在运行此命令之前,请确保您的系统中没有 usera 和 userb)
以具有 dbms_lock 的 grant privs 的用户身份连接,并且可以创建用户
Create a procedure which just does your lock and install it into a different user, who is "trusted" with dbms_lock ( USERA ), grant USERA access to dbms_lock.
Then just grant USERB access to this function. They then wont need to be able to access DBMS_LOCK
( make sure you don't have usera and userb in your system before running this )
Connect as a user with grant privs for dbms_lock, and can create users
从 Oracle 18c 开始,您可以使用 DBMS_SESSION.SLEEP过程:
DBMS_SESSION.sleep
可用于所有会话,无需额外授权。请注意,
DBMS_LOCK.sleep
已弃用。如果您需要简单的查询睡眠,您可以使用
WITH FUNCTION
:db<>fiddle demo
From Oracle 18c you could use DBMS_SESSION.SLEEP procedure:
DBMS_SESSION.sleep
is available to all sessions with no additional grants needed.Please note that
DBMS_LOCK.sleep
is deprecated.If you need simple query sleep you could use
WITH FUNCTION
:db<>fiddle demo
关于此主题有一篇很好的文章: PL/SQL :不使用 DBMS_LOCK 就睡觉,这帮助了我。我使用了封装在自定义包中的选项 2。建议的解决方案是:
There is a good article on this topic: PL/SQL: Sleep without using DBMS_LOCK that helped me out. I used Option 2 wrapped in a custom package. Proposed solutions are:
如果在“sqlplus”中执行,您可以执行主机操作系统命令“sleep”:
或
If executed within "sqlplus", you can execute a host operating system command "sleep" :
or
过程包装的 Java 代码怎么样?简单且运行良好。
What's about Java code wrapped by a procedure? Simple and works fine.
最好实现一个同步机制。最简单的方法是在第一个文件完成后写入一个文件。所以你有一个哨兵文件。
因此外部程序会寻找哨兵文件是否存在。当它这样做时,它知道它可以安全地使用真实文件中的数据。
另一种方法与某些浏览器下载文件时的做法类似,是将文件命名为 base-name_part,直到文件完全下载,然后最后将文件重命名为 base-name。
这样,外部程序在文件完成之前无法“查看”该文件。这种方式不需要重写外部程序。这可能最适合这种情况。
It would be better to implement a synchronization mechanism. The easiest is to write a file after the first file is complete. So you have a sentinel file.
So the external programs looks for the sentinel file to exist. When it does it knows that it can safely use the data in the real file.
Another way to do this, which is similar to how some browsers do it when downloading files, is to have the file named base-name_part until the file is completely downloaded and then at the end rename the file to base-name.
This way the external program can't "see" the file until it is complete. This way wouldn't require rewrite of the external program. Which might make it best for this situation.
您可以按如下方式使用
DBMS_ALERT
包:You can use the
DBMS_ALERT
package as follows:如果 Java 安装在您的 11G 上,那么您可以在 java 类中执行此操作并从 PL/SQL 中调用它,但我不确定它是否也不需要特定的授权来调用 java。
If Java is installed on your 11G then you can do it in a java class and call it from your PL/SQL, but I am not sure that it does not require also a specific grant to call java.
您可以将 DBMS_PIPE.SEND_MESSAGE 与对于管道来说太大的消息一起使用,例如,使用 5 秒超时将 XXX 延迟 5 秒写入只能接受一个字节的管道,如下所示
但是那么这需要 DBMS_PIPE 的资助,所以也许没有更好的了。
You can use
DBMS_PIPE.SEND_MESSAGE
with a message that is too large for the pipe, for example for a 5 second delay write XXX to a pipe that can only accept one byte using a 5 second timeout as belowBut then that requires a grant for
DBMS_PIPE
so perhaps no better.看来java过程/函数可以工作。但是为什么不在像应用程序架构这样的用户或具有此授权的管理员帐户下编译您的函数,并只授予您的开发人员帐户在其上执行。这样就可以使用定义者权限。
Seems the java procedure/function could work. But why don't you compile your function under a user like the application schema or a admin account that has this grant and just grant your developer account execute on it. That way the definer rights are used.
这是我的解决方案:
this is my solution:
您可以使用 DBMS_SESSION.SLEEP 替换 Oracle Database 18c 中的 DBMS_LOCK.SLEEP
https://oracle-base.com/articles/18c/dbms_session- sleep-18c#dbms_session
you can use DBMS_SESSION.SLEEP which replaces DBMS_LOCK.SLEEP in Oracle Database 18c
https://oracle-base.com/articles/18c/dbms_session-sleep-18c#dbms_session