Oracle PL/SQL过程的同步。如何保证一次只执行一个程序?
某些PL/SQL过程需要花费大量时间进行计算(因为需要重新计算和更新大量数据) 我想将评估此过程的执行上下文的数量限制为单个 如果有其他上下文执行它,就什么也不做 但我不知道在PL/SQL代码中使用哪些原子操作 注意:如果服务器在过程评估期间停止,使用表行进行同步可能会导致数据库中的状态不一致…您可以使用它生成唯一的锁句柄。只有一个会话可以同时持有此锁。如果会话的数据库重新启动意外结束,锁将自动释放 您可以在请求锁时决定是否在提交期间保持锁 下面是一个例子:Oracle PL/SQL过程的同步。如何保证一次只执行一个程序?,oracle,plsql,Oracle,Plsql,某些PL/SQL过程需要花费大量时间进行计算(因为需要重新计算和更新大量数据) 我想将评估此过程的执行上下文的数量限制为单个 如果有其他上下文执行它,就什么也不做 但我不知道在PL/SQL代码中使用哪些原子操作 注意:如果服务器在过程评估期间停止,使用表行进行同步可能会导致数据库中的状态不一致…您可以使用它生成唯一的锁句柄。只有一个会话可以同时持有此锁。如果会话的数据库重新启动意外结束,锁将自动释放 您可以在请求锁时决定是否在提交期间保持锁 下面是一个例子: SQL> CREATE OR
SQL> CREATE OR REPLACE PROCEDURE serial IS
2 l_lock_handle VARCHAR2(128 BYTE);
3 l_lock_request INTEGER;
4 BEGIN
5 dbms_lock.allocate_unique(lockname => 'MY_SERIAL_PROC',
6 lockhandle => l_lock_handle);
7 l_lock_request := dbms_lock.request(lockhandle => l_lock_handle,
8 timeout => 5,
9 release_on_commit => FALSE);
10 CASE l_lock_request
11 WHEN 0 THEN
12 NULL; -- success
13 WHEN 1 THEN
14 raise_application_error(-20002, 'lock already reserved');
15 ELSE
16 raise_application_error(-20001, 'Lock error: ' || l_lock_request);
17 END CASE;
18 BEGIN
19 ---------- serialized block of code ----------
20 ---------- (lock will be kept accross commit) ----------
21 dbms_lock.sleep(30);
22 ---------- End of serialized code ----------
23 EXCEPTION
24 WHEN OTHERS THEN -- release lock in case of uncatched error
25 l_lock_request := dbms_lock.release(lockhandle => l_lock_handle);
26 RAISE;
27 END;
28 l_lock_request := dbms_lock.release(lockhandle => l_lock_handle);
29 END;
30 /
Procedure created
我将同时运行两个会话:
Session A> exec serial;
Session B> -- Before session A ends
Session B> exec serial;
ERROR at line 1:
ORA-20002: lock already reserved
ORA-06512: at "APPS.SERIAL", line 13
ORA-06512: at line 1
PL/SQL procedure successfully completed
Session B> -- After session A ends
Session B> exec serial;
PL/SQL procedure successfully completed.
还要看一看DBMS_锁。您可以创建自己的名称锁,然后在PL/SQL包中获取该锁。如果包执行的另一个实例运行,锁调用将失败。这比锁定表或表中的行要高效得多,也不那么麻烦。+1很好!我不知道那个。我猜如果阻塞失败,事务会自动回滚,锁会被释放?@haki:不,事务不会回滚,锁也不会被释放!我可能应该在“finally”块中添加一个版本,因为这将是预期的行为,你是对的。谢谢-学到了一些东西。当其他人释放锁时,可以使用
异常编辑帖子。