代码之家  ›  专栏  ›  技术社区  ›  Nick Pierpoint

Oracle用户是否可以在没有访问v$session的情况下获得自己正在运行的会话的列表?

  •  2
  • Nick Pierpoint  · 技术社区  · 14 年前

    1. 使用对象锁阻止后续进程运行。

      这样可以,但我希望调用会话立即返回,而不是等待正在运行的会话完成。

    2. 使用自定义Y/N设置进程是否正在运行。

      我在进程开始时设置了一个“Y”标志,在进程完成或失败时将其设置为“N”。也很好,但感觉像是我在重新发明方向盘,感觉不太对劲。当标志停留在“Y”时,如果正在运行的会话被终止,那么它也会失败。

    3. 使用 dbms_application_info.set_module

      这种方法看起来最健壮,但是如果我想知道有一个正在运行的进程,我想我需要能够查询 v$session 我不希望这个应用程序有如此广泛的访问权限。

    有什么想法吗?

    3 回复  |  直到 14 年前
        1
  •  6
  •   Rob van Wijk    14 年前

    选项4:使用DBMS\ U锁序列化访问。以下是文档的链接: http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10577/d_lock.htm#i1002556

    举个例子:

    首先创建一个辅助过程来序列化对某个过程的访问。该过程使用过程的名称来生成唯一的锁句柄。“NOTORA$”以确保lockname不以“ORA$”开头,因为它们是为Oracle保留的。

    SQL> create procedure serialize_access (p_procedure_name in varchar2)
      2  is
      3    l_lockhandle varchar2(128);
      4    l_return     integer;
      5  begin
      6    dbms_lock.allocate_unique
      7    ( lockname   => 'NOTORA$' || p_procedure_name
      8    , lockhandle => l_lockhandle
      9    );
     10    l_return := dbms_lock.request
     11    ( lockhandle        => l_lockhandle
     12    , lockmode          => dbms_lock.x_mode
     13    , timeout           => 0  -- do not wait
     14    , release_on_commit => true
     15    );
     16    if l_return = 1
     17    then
     18      raise_application_error
     19      ( -20000
     20      , 'Someone else is running this procedure, so you''ll have to wait'
     21      );
     22    end if;
     23  end serialize_access;
     24  /
    
    Procedure created.
    

    在您的过程中,按如下方式调用此serialize\u访问过程:

    SQL> create procedure p1
      2  is
      3  begin
      4    serialize_access('p1');
      5    dbms_lock.sleep(30);
      6  end;
      7  /
    
    Procedure created.
    

    其中dbms\u lock.sleep被用作真实代码的替换。 现在打开另外两个或多个会话并发出“execp1”命令。第一个会话将以等待30秒开始。第二节课将向您展示:

    ERROR at line 1:
    ORA-20000: Someone else is running this procedure, so you'll have to wait
    ORA-06512: at "[schema].SERIALIZE_ACCESS", line 18
    ORA-06512: at "[schema].P1", line 4
    ORA-06512: at line 1
    

    当做,

        2
  •  1
  •   dpbradley    14 年前

    在生产环境中,当会话失败或挂起时,#1/#2通常需要一些手动干预。

        3
  •  1
  •   Stephanie Page    14 年前

    DBMS\u LOCK的答案很好,但似乎有点复杂。。。但那只是一次,所以没关系。

    一个非常简单的方法是创建一个配置表。。。可能只有一列“name”

    当您需要锁时,请执行以下操作:

    选择name INTO var FROM config,其中name='lock\u name'用于UPDATE NOWAIT;

    释放锁的方式是通过提交;或回滚;如果会话结束(通常),您的会话将执行此操作。

    如果出现新的单线程进程,则可以向表中添加更多行。你甚至可以把NOWAIT改成WAIT。这样,下一个实例就可以等待10秒或其他时间来查看是否可以获得锁。那将是保持一个人“永远站起来”的最好方法