2012-03-22 24 views
12

proceduremyprocと言われています。これは複雑なプロセスなので、同時に2つのインスタンスを実行することはできません。Oracleで複数回プロセスを実行しないようにする最良の方法はありますか?

実は私はこのdbms_application_info.set_moduleを使用してください:

procedure start_process is 
begin 
    dbms_application_info.set_module('myproc', 'running'); 
end; 

およびプロセスを実行する前に確認してください:データベースレベルで

select 'S' 
    from v$session v 
where v.module = 'myproc' 
    and v.action = 'running'; 

を、これをチェックする良い方法はありますか?

+1

+1良い質問ですが、 'v $ session'はモジュール上で一意ではないので、間違っている可能性があります。 – Ben

+0

も参照してください。http://stackoverflow.com/questions/1053484/block-procedure-pl-sql-with-oracle – gavenkoa

答えて

9

使用dbms_lock.allocate_uniquedbms_lock.requestと一緒に。 使用上の注意言う:

新しいロック名でALLOCATE_UNIQUEをコールする最初のセッションはDBMS_LOCK_ALLOCATEDテーブルに作成して保存する ユニークなロックIDを引き起こします。 その後のコール(通常は他のセッションによる)は、以前に生成されたロックIDを返します。

私はこれがあなたが何をしているのかと思います。

+0

+1、これは私よりはるかに良いアイデアです...私はあまりにも多くのメタデータを他のことと同時に収集することに慣れています。 – Ben

+0

本当に興味深い機能。ありがとう! –

1

テーブルprocessesを作成することができます。また、各プロセスにある種の一意の識別子があることも確認してください。たとえば、のプロセスでは、dba_objectsからのowner, object_nameというハッシュがあります。

次に、プロセスが実行されるときにlock each row individuallyに関数を作成します。

@Sergioがコメントで指摘したように、何らかの理由でプロセスの途中でコミットする必要があった場合、各コミット後に再選択しない限り、これはうまくいきません。

function locking (Pid) return number is 

    l_locked number := 0; 

begin 

    select 1 
    into l_locked 
    from processes 
    where id = Pid 
     -- exit immediately if the proc is running 
     for update nowait 
      ; 

    return l_locked; 

    exception when others then 
     return 0; 

end; 

これは、現在お使いの手順を実行しているセッションが終了するまで、あなたのためprocessesでその行をロックする利点を有します。

次に、あなたの手順でこれをラップ:

-- if we failed to lock locking will have thrown an error 
-- i.e. we have 0 here. 
if locking(123) = 0 then 
    exit; 
end if; 

限り、それぞれの手順では、固有のIDがあるとして - 重要なビット - あなたの手順が正常に終了しますが。


それはあなたの状況には適用されないかもしれないが、これを行うための私の通常の方法は、modを使用することです。同じプロセスを実行している間に2つのプロセスが停止するわけではありませんが、1つ以上のプロセスが異なるデータでのみ実行されるようにします。次のような何か:

procedure my_procedure (PNumerator number, PDenominator number) is 

    cursor c_my_cursor (CNumerator number, CDenominator number) is 
    select columns 
     from my_table 
     where mod(ascii(substr(id, -1)), CDenominator) = CNumerator 
      ; 

begin 
    open c_my_cursor(PNumerator, PDenominator); 
    ...  
end; 
+0

プロセスの途中で何らかの理由でコミットする必要がある場合は、これが壊れました。 –

+0

@SérgioMichels、良い点!私はそれを答えに加えます。 – Ben

関連する問題