2009-06-08 3 views
3

SQL 문을 시간 초과하여 쉽게 실패 할 수있는 쉬운 방법입니다 (예 : 빈 결과 집합이나 오류 메시지 등을 전달하는 것). 다른 사람) 그래서 나는 일자리의 ressource 예약을 실패하게하고 또 다른 기회를 줄 수 있을까? 나는 지금까지 간과 한 DBI 옵션을 찾고있다. 내가 SIGALRM을 자살하기 위해 보내는 것은 오히려 내가 염두에두고있는 것과 다르다.Perl DBI를 사용하여 Oracle에서 "select for update"를 타임 아웃하는 방법 DBI

코드를 잘라내어 극단적으로 짧게 만들었지 만 표류를 잡으시기 바랍니다. Oracle 테이블을 사용하여 구현 ressource 잠금기구가 대규모 병렬 numbercrunching을 수행하는 응용 프로그램

: 여기

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); 

는 유혈 관심에 대한 상세이다. 각 작업은 읽기 용으로 여러 자원을 잠글 필요가 있으며 기록 할 자원의 수를 잠글 수 있습니다. 모든 잠금이 성공적으로 획득 된 경우에만 시작할 수 있습니다. 리소스가 해제되기를 참을성있게 기다리는 대신에, 작업은 실패하고 나중에 마스터에서 다시 실행해야합니다 (이로 인해 열린 트랜잭션 수가 낮아지며 실제로 작업량이 늘어남에 따라 성능이 향상됩니다).

물론 실제로 테이블을 업데이트하기 전에 각 행은 SELECT ... FOR UPDATE 문을 사용하여 예약되므로 Oracle은 행 수준 잠금을 사용하고 테이블에서 동시 트랜잭션이 발생할 수 있습니다. 가능한 경쟁 조건 및 교착 상태를 더 줄이기 위해 모든 작업은 먼저 해당 자원 행을 선택하고 업데이트를 수행하기 전에 동일한 순서를 사용하여 행을 잠급니다.

현재 구현에서이 경우는 의 경우 대부분에서 잘 작동합니다. 그러나 오라클이 실제로 행 잠금을 허용 할 때까지 "업데이트 선택"블록을 사용하기 때문에 작업이 유휴 상태가되어 자원을 기다리는 경우가 발생할 수 있으며 사용 가능한 CPU 성능을 더 잘 활용할 수 있습니다. 잠 그려면 2 ~ 2 초 정도 기다려도되지만 10 회 이상 기다리지 않아도됩니다. un 나중에 잠그기 위해서는 대기가 필요하므로 즉각적인 결과 만 받아들이도록 전체 DB 연결을 설정하면 작동하지 않습니다.

나는만큼 그들이 M의 위치를 ​​가리 나는이 TFR ;-))

미리 감사를해야하는 RTFM 답을 항상 감사 해요 ,
Olfan

+1

"커밋 자살"이란 무엇입니까? 원하는대로 처리하도록 SIGALRM 핸들러를 설정할 수 있습니다. 신호를 모두 피하려고하는 것입니까? – jiggy

+0

마스터 프로세스 만 신호를 처리하도록 열심히 노력하고 있습니다. 어쩌면 펄은 실제로 그것을 처리 할 수 ​​있지만, 내 두뇌 구조는 아버지와 자식 과정에서 서로 다른 신호 처리를 할 준비가되어 있지 않습니다. – Olfan

답변

7

FOR UPDATE 절에 NOWAIT 매개 변수가 필요하다고 생각합니다. 레코드를 잠글 수없는 경우, 선택은 실패합니다 ("ORA-00054 : 리소스 사용 중이며 NOWAIT로 획득") 하지만 예외는 처리 할 수 ​​있습니다. SQL Reference manual을 확인하십시오. 11g이지만 구문은 여러 버전에서 변경되지 않았습니다.

또 다른 옵션은 기다릴 시간을주는 것입니다. "FOR UPDATE WAIT 3"은 즉시 실패하지 않고 잠금을 획득하기 위해 3 초 동안 대기합니다.

+1

감사합니다. 왜 SQL 자체가 내가 원하는 옵션을 이미 가져 왔을 때 Perl과 DBI를 사용하는 이유는 무엇입니까? ;-) 이것은 이미 구현되어 있으며 다음 변경 창에서 실시간으로 실행됩니다. 다시 한번 감사드립니다. – Olfan

+0

Perl/DBI에는 괴짜 지수가 있습니다 ;-) – DCookie

+0

대기 시간은 설정 가능한 옵션과 함께 실시간입니다. 이 변경 사항을 저장하는 대부분의 시간이 대용량 저장을 기다리는 데 소비되고 있지만 (내 다음 대상 ;-) 전체 CPU 사용률 (= 원시 처리량)은 거의 2 % 증가하여 절대적으로 가치가 있습니다. – Olfan

2

실제로 SIGALRM은 그렇게 나쁘지 않을 수도 있습니다. 일부 옵션은 here입니다.

+0

물론 당신 말이 맞습니다. 그러나 저는 작업자 프로세스가 자신의 신호 처리를 구현하지 못하도록하고 싶습니다. 특히 작업 프로세스가 자신의 아버지 프로세스가 구현 한 프로세스와 다른 경우 특히 그렇습니다. – Olfan