문제

어떻게 든, 나는 항상 금요일에 이것을 얻습니다.

나의 초기 질문은 같은 문제에 관한 것이었지만 이제는 조금 좁힐 수 있습니다.

나는 하루 종일 놀면서 그것을 이해하려고 노력했다. leop_version colum이있는 테이블이 있습니다.

add_column :jobs, :lock_version, :integer, :default=>0

그리고 나는 다음과 같은 일을합니다.

foo = job.create!
first = Job.find(foo.id)
second = Job.find(foo.id)

그런 다음 첫 번째와 두 번째가 동일한 객체를 참조하는지 확인합니다. ID는 동일하며 MySQL 명령 줄 도구를 사용하여 데이터베이스의 행을 볼 수 있습니다.

first.some_attribute_field = 'first'
second.some_attribute_field = 'second'
first.save
second.save

지금까지 문제가 없습니다. ActivereCord :: StaleObjecterror 예외를 올바르게 얻습니다. 하지만:

first = Job.find(foo.id)
second = Job.find(foo.id)
first.some_attribute_field = 'first'
second.some_attribute_field = 'second'
first.save
second.save

... 그리고 아무 일도 일어나지 않습니다. 내가 올바른 (예외를 던진) 동작을 얻는 유일한 시간은 첫 번째와 두 번째가 0의 잠금 장치를 가질 때입니다. 그러나 첫 번째 저장 후에는 다시는 0이 아닙니다. 이 지구상에서 무슨 일이 일어나고 있습니까?

Ruby 1.8.6과 Active Record 2.2.2를 사용하고 있습니다

감사...

도움이 되었습니까?

해결책

두 번째로 전화하면 some_attribute_field의 값은 이미 "첫 번째"와 동일합니다. ActiveRecord는 이것을 알고 있으므로 DB에서 leop_version으로 업데이트되지 않으므로 증가하지 않습니다. 두 번째 저장은 DB가 "첫 번째"로 변경되지 않았기 때문에 작동합니다.

두 번째 테스트의 값을 DB에있는 것과 다르기 위해 "첫 번째"이외의 다른 것으로 변경하십시오.

다른 팁

나는 루비 남자는 아니지만 낙관적 잠금은 나에게 친숙하므로 디버깅을 도와 줄게.

두 번째 저장은 실제로 데이터베이스를 업데이트한다고 가정합니다. 두 객체의 잠금 장치가 다르고 leop_version이 업데이트에 사용되면 단순히 불가능합니다 (업데이트는 0 행을 업데이트합니다). 따라서 두 가지 대안 만 있습니다.

  • Lock_version은 업데이트 문에 사용되지 않거나 잘못 사용됩니다.
  • 두 개체 모두 어떻게 든 동일한 잠금 장치를 얻었습니다

(실제로 세 번째 대안이 있습니다. Save ()는 자체 거래에 있지만 AutoCommit = True가 있다고 생각합니다.)

실제 SQL 문을 보이게 할 수 있습니까? 업데이트 명령문은 같은 것을 읽어야합니다

... WHERE JOB_ID=123 AND LOCK_VERSION=8

실제로 쿼리를 할 때 무슨 일이 일어나고 있는지 이해하는 것이 훨씬 쉬울 것입니다.

추신 및 한 가지 더 : 다른 주제의 예에서는이 객체가 있습니다.

#<Job id: 323, lock: 8, worker_host: "second">

로드 시간과 비교하여 속성이 변경되지 않으면 컨테이너로 저장 () 호출을 무시할 수 있습니다. ActiveRecord 에이 최적화가 있는지 여부는 모르겠습니다. 그러나 그렇다면 두 번째 저장 ()가 무시되고 낙관적 잠금은 시작될 기회가 없습니다.

Vladimir가 말했듯이 테스트/예제 코드는 약간 결함이 있습니다. 먼저 속성이 변경되지 않았기 때문에 두 번째 저장 중에 DateBase에 저장되지 않습니다! (). 다음 예를 참조하십시오.

foo = Account.create!

first = Account.find(foo.id)
first.cash = 100
first.save!


first = Account.find(foo.id)
first.cash = 100

puts "First lock before " + first.lock_version.to_s
first.save!
puts "First lock after " + first.lock_version.to_s

이것은 생성됩니다 :

% script/runner another_tester.rb                               
First lock before 1
First lock after 1

2.3.2 버전의 Rails에서 예제를 사용하면 두 번째 저장이 저장 될 때 오래된 객체 예외가 있어야합니다 (두 번 모두!)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top