2016-06-15 11 views
2

DB에서 모든 사용자에 대해 실행되는 긴 프로세스가 있고 "score"및 "hits"필드가 업데이트되는 동안이 프로세스가 실행되는 동안 사용자가 자신의 이름/전화를 업데이트하려고 시도하는 경우가 있습니다 등 지금이 사용자 업데이트를 발생할 때 실패 :hibernate가 업데이트 할 때 레코드 잠금을 방지합니다.

org.springframework.dao.CannotAcquireLockException 
could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement 

것은 내가 그 점수의 사용자 캔트 업데이트/필드 안타 것을 알고, 그래서 내가 두 업데이트를 모두 고정되는 행을 방지 할 수 있습니다 달리기?

BTW 내가 자바 8 스프링 부팅 1.3.3.RELEASE를 사용하고 (난 쿼리가 변경된 필드를 업데이트하기 때문에 그 잠금을 방지 할 생각했기 때문에 내가하지만 운이없이, @DynamicUpdate 최대 절전 모드를 사용하고 있습니다) (바람둥이에서 실행.

* UPDATE *

업데이트. 나는 모든 사용자가 한 번. 갱신이 있어야 안타 내가 모든 사용자 점수 하나의 큰 트랜잭션을 사용하고 @Thierry 질문/답변을하고, 또한이 프로세스가 실행되는 동안 사용자가 자신의 레코드를 업데이트하지 못하도록 방지합니다. ystem.

는 * UPDATE *

2 그래서 검색을 많이 후 나는 내가 원하는 정확하게 찾을 생각합니다. 이 기사에 따르면 : http://www.intertech.com/Blog/hibernate-optimistic-lock-without-a-version-or-timestamp/, 나는 잠금 유형을 더티 및 동적 업데이트로 낙관적 인 잠금을 설정할 때 : "이 대안을 사용하면 동일한 열을 수정하지 않는 한 다른 동시 프로세스가 동일한 행을 업데이트 할 수 있습니다."

@DynamicUpdate 
@OptimisticLocking(type = OptimisticLockType.DIRTY) 
@Entity 
public class User { .. 

그리고 난 여전히 잠금 예외가 : 것은 Iv'e이 나의 실체를 설정합니다. 나는 여전히 뭔가 잘못하고 있니?

답변

1

업데이트 된 사용자 레코드를 임시로 다른 테이블에 저장하고 장기 실행 프로세스가 완료되면이 데이터를 사용자 테이블에 저장하는 또 다른 프로세스가 있습니다 (장기 실행 프로세스의 마지막 단계 일 수도 있음).

프로필 페이지를 사용자 (또는 사용자가 레코드를 업데이트 할 수있는 페이지)에 표시 할 때 주 사용자 테이블 (잠길 수 있음)과 다른 테이블 내부의 데이터를 집계해야합니다.

사용자 레코드를 업데이트 할 때 CannotAcquireLockException을 잡아서 정보를 대체 테이블에 저장하십시오.

+0

Iv'e가 내 질문을 업데이트하여 질문에 답변했습니다. 사용자를 계속 유지하려는 경우 제안한 첫 번째 옵션을 사용할 수 없습니다. 두 번째는 나에게 나쁜 해킹 소리가 난다. 프로세스가 끝나면 레코드를 잠그는 데 시간이 걸리는 모든 사용자를 업데이트해야하기 때문에 도움이 될 것이라고 확신 할 수 없다. – Osher

+0

@Osher. 좋아, 그래서 볼 수있는 유일한 해결책은, 내 대답의 마지막 부분입니다 : 일시적으로 업데이트 된 레코드를 저장할 다른 테이블을 만듭니다. 실행중인 프로세스가 완료되면 주 사용자 테이블로 피드를 보냅니다. 프로필 페이지를 사용자에게 표시 할 때 주 사용자 테이블 (잠길 수 있음)과 다른 테이블 내부의 데이터를 집계해야합니다. (나머지 부분은 더 이상 관련이 없으므로이 마지막 부분 만 표시하도록 답변을 업데이트했습니다.) – Thierry