2017-10-18 11 views
0

나는 최대 절전 모드의 낙관적 잠금 (전용 버전 방식)에 대해 궁금해한다. 현재 트랜잭션이 커밋되기 전에 버전을 확인한다는 내용의 최대 절전 모드 소스 코드를 확인했지만, 쿼리가 끝난 후 다른 트랜잭션이 커밋 된 경우 DB의 버전 열 (매우 짧은 시간 간격)에서 현재 트랜잭션은 변경 사항이없는 것으로 간주하므로 이전 트랜잭션이 잘못 대체됩니다. 이러한 경우에 가능한최대 절전 모드 낙관적 잠금 메커니즘

EntityVerifyVersionProcess.java

@Override 
    public void doBeforeTransactionCompletion(SessionImplementor session) { 
     final EntityPersister persister = entry.getPersister(); 

     if (!entry.isExistsInDatabase()) { 
      // HHH-9419: We cannot check for a version of an entry we ourselves deleted 
      return; 
     } 

     final Object latestVersion = persister.getCurrentVersion(entry.getId(), session); 
     if (!entry.getVersion().equals(latestVersion)) { 
      throw new OptimisticLockException(
        object, 
        "Newer version [" + latestVersion + 
          "] of entity [" + MessageHelper.infoString(entry.getEntityName(), entry.getId()) + 
          "] found in database" 
      ); 
     } 
    } 

입니까?

DB 도메인 전문가가이 문제에 도움이되기를 바랍니다.

감사합니다.

+0

이렇게하면 깨지거나 쓸모 없게됩니다. 아주 좋은 광고는 "낙관적 인 잠금을 사용합니다. 보통 데이터를 손상시키지 않습니다!". – Kayaman

+0

흠, 실제로 그것은 중복 질문이라고 생각하지 않습니다. 그 질문은 낙관적 인 잠금 메커니즘에 관한 것입니다. 그러나 저는 아닙니다 ... – user2015063

+0

당신은 뭘하지 않았습니까? 그것은 당신이 말하는 것과 똑같은 것 같습니다. 그리고 아니요, 물건을 깰 기회가 없습니다. 낙관적 인 잠금이 실패하면 하나의 트랜잭션이 롤백됩니다. – Kayaman

답변

1

코드를 간략하게 보면 EntityVerifyVersionProcess이 읽기 ​​트랜잭션에 사용되므로 데이터 손실의 위험이 없습니다. 이렇게하면 트랜잭션이 커밋 될 때 이미 오래된 데이터가 반환되지 않는지 확인합니다. READ COMMITTED 트랜잭션을 사용하면이 데이터가 즉시 부실로 표시되지만 세부 정보로 이동하지 않고 말하기 어렵다고 가정합니다.

다른 거래에서 쓰기 거래는 EntityIncrementVersionProcess으로 완전히 다른 짐승이며 경쟁 조건이 없습니다.

public void doBeforeTransactionCompletion(SessionImplementor session) { 
    final EntityPersister persister = entry.getPersister(); 
    final Object nextVersion = persister.forceVersionIncrement(entry.getId(), entry.getVersion(), session); 
    entry.forceLocked(object, nextVersion); 
} 
+0

그래서 (OptimisticLock)는 "SELECT xxx FOR UPDATE"방법을 사용하여 긴 트랜잭션에 대한 레코드를 처음부터 잠그지 않고 잠그는 것이 좋습니다. 귀하의 도움에 감사드립니다. – user2015063

+0

아니요 아니요. 트랜잭션 기간 동안 레코드를 잠그는 업데이트 선택이 없습니다. 내부 동작이 단순하지 않고 질문의 코드가 * updates *를 처리하지 않고 * select * 만합니다. 만약 당신이 업데이트를 수행한다면, 다른'* Process' 클래스가 포함되어 있지만 내부 동작이 너무 잘되어서 플로우가 어떻게 진행되는지 정확히 설명 할 수는 없습니다. 내부적으로는 버전이 증가한 경우 실패하는'update foo WHERE version = @ oldversion'이 내부적으로 존재하며 db의 가능한 경쟁 조건을 피합니다. – Kayaman

+0

코드 세부 사항을 살펴 보겠습니다. – user2015063