2009-06-08 34 views
3

SQLステートメントをタイムアウトさせる簡単な方法があります(たとえば、空の結果セットやエラーメッセージなどを配信するなど)。そうでなければ、私は仕事のressource予約を失敗させて、別のチャンスを与えることができますか?私はこれまで見落としてきたDBIオプションを探しています。自殺のためにSIGALRMを自分自身に送ることは、私が心に留めていることではなく(私がしなければならないことに頼らざるを得ないかもしれないが)。Perl DBIを使用してOracleの「select for update」をタイムアウトさせるには

コードを擬似化して極端に短くしていますが、ドリフトをキャッチしていただければ幸いです。ここ

my $sql = "SELECT one, two, three FROM sometable WHERE this = ? AND that = ?"; 
my $sth = $self->make_handle($sql); 
eval { 
    foreach my $this (sort keys %needed_ressources) { 
     # vvv This is where the idle time is spent vvv 
     $sth->execute($this, $that) or die("DB connection gone?!"); 
     # ^^^ This is where the idle time is spent ^^^ 
     my ($one, $two, $three) = $sth->fetchrow_array(); 
     unless($one) { # undefined record set == not found 
      $self->{DB_HANDLE}->rollback(); 
      die("$this not defined for $that!"); 
     } 
    } 
    # If we haven't died so far, we can move on 
    foreach... #similar loop here doing the actual update statement 
    $self->{DB_HANDLE}->commit(); 
}; 
return(1) unless [email protected]; 
return(undef); 

興味のための血みどろの詳細は、次のとおりOracleテーブルを使用して実装さressourceロック機構が存在する大規模並列numbercrunchingを行うアプリケーションにおいて

。各ジョブは、読み取りのためのいくつかのリソースと書き込みのためのいくつかのリソースをロックする必要があり、すべてのロックが正常に取得された場合にのみ起動できます。リソースが解放されるのを辛抱強く待つ代わりに、ジョブはただ失敗し、後でマスタによって再実行される必要があります(これにより、開いているトランザクションの数が少なくなり、パフォーマンスが向上します。

もちろん、実際に表を更新する前に、各行は「SELECT ... FOR UPDATE」文を使用して予約されているため、Oracleは行レベルのロックを使用し、同時トランザクションは表で実行されます。可能な競合状態とデッドロックをさらに減らすために、すべてのジョブは最初に再ソース行を選択し、更新を実行する前に同じ順序を使用して行をロックします。

現在の実装では、これはの場合、ほとんどのケースで問題なく動作します。しかし、Oracleが実際に行ロックを許可するまで、「更新のための選択」ブロックが存在するため、ジョブがそのリソースを待っている間アイドル状態になっている可能性があります。ロッキングのためにちょうど1,2秒待つのはOKですが、10秒以上待ってはいけません。 の場合はのロックが必要ですが、待機する必要がありますので、DB接続全体を設定するとすぐに結果を受け入れることはできません。

は私がいる限り、彼らはM内の場所を指すように私はTFR ;-))

事前のおかげで多くを持っていなければならないことRTFM答えをいつも感謝しています、
Olfan

+1

「コミットコミット」とはどういう意味ですか? SIGALRMハンドラを設定して、必要な処理を行うことができます。信号だけを避けようとしていますか? – jiggy

+0

私は、マスタープロセスだけがシグナルを処理するように努力しています。たぶんPerlは実際にそれを扱うことができるかもしれませんが、私の内部の脳構造は、父と子の両方のプロセスで異なるシグナルハンドリングを持つ準備ができていません。 – Olfan

答えて

7

私はNOWAITパラメータがFOR UPDATE句に必要と思うと思います。レコードをロックできない場合、選択は失敗します(「ORA-00054:リソースがビジーであり、NOWAITで取得します」)。 が必要ですが、例外を処理できます。 SQL Reference manualをチェックしてください。 11gですが、いくつかのバージョンで構文が変更されていません。

もう1つの方法は、すぐに失敗するのではなく、ロックを取得するために3秒間待機する「FOR UPDATE WAIT 3」を待機させることです。

+1

これは素晴らしいことです。ありがとうございます。 PerlとDBIでSQL自体が既に必要なオプションを持ってきたのはなぜでしょうか? ;-)これは既に実装されており、次回の変更ウィンドウで有効になります。再度、感謝します。 – Olfan

+0

Perl/DBIのギーク商はより大きくなります;-) – DCookie

+0

これはライブです。待ち時間は設定可能なオプションです。この変更の節約は大容量ストレージを待っているだけですが(私の次の目標;-)、全体的なCPU使用率(= rawスループット)はほぼ2%向上しています。 – Olfan

2

実際、SIGALRMはあまりにも悪くないかもしれません。一部のオプションはhereと記載されています。

+0

もちろん、あなたは正しいです。しかし、実際には、父親のプロセスが実装したプロセスとは異なる場合には、ワーカープロセスが独自のシグナル処理を実装しないようにしたいと考えています。 – Olfan

関連する問題