2014-11-07 2 views
6

일부 원시 DBI 호출을 DBIx :: Class로 변환하려고합니다. 때때로 다음과 같은 것을 실행합니다 :DBIx :: Class를 사용하여 열을 증가시키는 방법?

UPDATE 'foo' SET bar = bar + 1 WHERE ... 

DBIx :: Class가 정확하게 이런 종류의 쿼리를 실행하도록 할 방법이 있습니까? 나는 다음과 같은 일을하고 싶지 않습니다 :

여러 프로세스가 같은 일을하려고 할 때 거기에 경쟁 조건이 있기 때문입니다.

데이터베이스 수준에서 어떤 종류의 잠금을 사용하면 문제가 발생할 수 있지만 원래 쿼리를 사용하는 것보다 나에게 나빠질 것 같습니다. 기본적으로 나는 이것을하기 위해 DBIC를 사용하는 깨끗한 방법이 있는지 알고 싶습니다. 아니면 여기에서 원시 DBI 호출을 계속 사용해야 만하는지 알고 싶습니다.

+0

'$ 행 -> {bar}'가 아니라'$ row-> bar() ' – TLP

+0

대개 카운터가 1 씩 증가합니다. 이 분야에서 어떤 종류의 경쟁 조건이 발생하고 있습니까? –

+0

@TLP 나는 $ row-> bar()를 의미했다. $ row는 DBIC 결과 객체이다. – oalders

답변

3

를 사용하여 솔루션과 같은 트랜잭션 코드의 당신의 블록을 포장하지만 updateupdate_all을 대체 할 수

$rs->search(...)->update({ 
    bar => \'bar + 1', 
}); 

이것은 하나의 UPDATE 문에서 발생합니다. (설명 :.. update_all DBIC 트리거 같은 것들을 포함 된 ResultSet의 모든 행에 update를 호출하여 작동하므로 먼저 행을 가져 update을는 ResultSet에있다가 베어 SQL의 UPDATE를 실행) 나는 당신이 의미 가정

0

DBIx :: Class :: Storage :: TxnScopeGuard 도움말을 사용합니까? 당신은 @ ThisSuitIsBlackNot의 코멘트에서이

my $guard = $schema->txn_scope_guard; 
# your increment 
$guard->commit; 
+1

이 경우에는 문제가 완전히 해결되지 않고 읽기 시간과 쓰기 시간에 문제가 발생합니다. @ThisSuitIsBlackNot의 의견은 아마도 이것을 수행하는 가장 깨끗한 방법이라고 생각합니다. – oalders

+0

@oalders - 예, 감사합니다. –

관련 문제