동일한 엔티티 (사용자)에 대해 여러 개의 Resque 작업자가 있습니다. 처리가 성공적으로 완료되면 call_left
속성이 감소해야합니다.ActiveJob/Resque 더티 읽기. 트랜잭션 격리 수준
(결과적으로) perform_now
과 완벽하게 작동하지만 perform_later
(예상치 못한 결과) (병렬로). 로그에는 calls_left
과 동일한 수의 커밋이 있습니다.
나는 reload
메서드를 사용하려고 시도하고 심지어 가장 높은 격리 수준을 설정했습니다. 그러나 여전히이 문제가 있습니다.
해결 방법은 무엇입니까?
class DataProcessJob < ActiveJob::Base
queue_as :default
def perform(user_id, profile_id)
User.transaction(isolation: :serializable) do
user = User.find(user_id).reload
user.data_process(profile_id)
user.update(calls_left: user.calls_left-1)
end
end
end
잠금이 작동하지 않습니다. 낙관적 인 것은 단일 프로세스에서 작동하도록 설계 되었기 때문에 작동하지 않습니다. 비관적 인 것 - 그냥하지 않습니다. 원시 SQL이 작동하는 것 같습니다. 감사합니다. –
사실, 레일즈는 테이블에'lock_version' 필드를 추가하여 낙관적 인 잠금을 구현합니다 (DB 레벨 낙관적 잠금과는 약간 다릅니다). 따라서 SQL 업데이트 쿼리에서 잠금 버전 검사를 구현하면 비 단일 프로세스 시나리오에서 작동합니다. 그러나, 나는 확실하지 않다, 소스 코드를 들여다 보지 않았다. 낙관적 잠금을 사용해 보셨습니까? 네가 해줬고 효과가 없다면 알려줘. 미래를 위해 이것을 메모하는 것이 좋을 것입니다. – Uzbekjon
낙관적 잠금은 기본적으로 설정되어 있습니다. 필자의 경우 object가 시대에 뒤진 경우'Rescue ActiveRecord :: StaleObjectError'를 발생시킵니다. 그리고이 문서의 내용입니다 : '이 잠금 메커니즘은 단일 Ruby 프로세스 내에서 작동합니다. 모든 웹 요청에서 작동되게하려면 lock_version을 양식에 숨겨진 필드로 추가하는 것이 좋습니다 .' –