SQL ステートメントをタイムアウトして、ジョブのリソース予約を失敗させ、別のリソース予約にチャンスを与えることができるように、待機する代わりに失敗する (たとえば、空の結果セットやエラー メッセージなどを配信するなど) 簡単な方法はありますか? これまで見落としていた DBI オプションを探しています。自殺するために SIGALRM を自分に送信することは、私が考えていることではありません (必要に応じてそれに頼る必要があるかもしれませんが)。
切り取ったコードは極限まで疑似化・短縮化していますが、ズレを掴んでいただければ幸いです。
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 $@;
return( undef );
興味のある人のための悲惨な詳細は次のとおりです。
大規模な並列処理を行うアプリケーションでは、Oracle テーブルを使用するリソース ロック メカニズムが実装されています。各ジョブは、読み取り用の多数のリソースおよび/または書き込み用の多数のリソースをロックする必要があり、すべてのロックが正常に取得された場合にのみ開始できます。リソースが解放されるのを辛抱強く待つのではなく、ジョブが失敗して後でマスターによって再実行される必要があります (これにより、実際にクランチするジョブが増えることでパフォーマンスが向上し、開いているトランザクションの数が少なくなります)。
もちろん、実際にテーブルを更新する前に、「SELECT ... FOR UPDATE」ステートメントを使用して各行が予約されているため、Oracle は行レベルのロックを使用し、テーブルで同時トランザクションが発生する可能性があります。競合状態とデッドロックの可能性をさらに減らすために、すべてのジョブはまずリソース行を選択し、更新を実行する前に同じ順序で行をロックします。
現在の実装では、これはほとんどの場合にうまく機能します。しかし、「Select for update」は Oracle が実際に行ロックを許可するまでブロックされるため、ジョブがアイドル状態でそのリソースを待機している可能性があります。1 ~ 2 秒待つのは問題ありませんが、ロックのためだけに 10 秒以上待つことはできません。後でロックを解除するには、もちろん待機が必要であるため、DB 接続全体を即時の結果のみを受け入れるように設定しても機能しません。
TFがRを持っている必要があるMの場所を指している限り、 RTFMの回答には常に感謝しています;-))
事前にどうもありがとう、
オルファン