2013-03-08 2 views
2

datastore documentation는 말한다 :동시 쓰기 전용 거래

엔티티 그룹에 대한 트랜잭션을 커밋하면, 앱 엔진을 다시 체크 거래에 사용되는 엔티티 그룹의 마지막 업데이트 시간. 우리의 초기 검사, 앱 엔진 예외

를 발생 이후 변경된 경우 나는 두 개의 동시 트랜잭션에 new Entity("TestEntity",1)의 거래 데이터 저장소 넣어 수행하는 방법에 대한 세 가지 테스트 케이스를 가지고있다.

  • test1 : 첫 번째 트랜잭션에 엔터티를 넣고 두 번째 트랜잭션에 엔터티를 넣고 두 트랜잭션을 커밋하십시오. 이 테스트는 개발 서버 및 독립형 유닛 테스트에서 실행될 때 (즉, ConcurrentModificationException) 성공하지만 프로덕션 서버에서 실행될 때 실패합니다 (예외를 발생시키지 않고 실행 함).

  • test2 : 엔티티를 첫 번째 트랜잭션에 넣고 커밋 한 다음 엔티티를 두 번째 트랜잭션에 넣고 커밋합니다. 이 테스트는 항상 실패합니다.

  • test3 : 두 트랜잭션에서 (존재하지 않는) 엔티티를 가져 와서 test2하십시오. 이 테스트는 항상 ConcurrentModificationException을 던져 통과합니다. 나는 결론이 테스트에서

beginTransactionput 보장도 그 "초기 검사가"를 수행하고, 나는 트랜잭션의 무결성을 보장하기 위해를 얻을 지불 할 필요가있다. 그 맞습니까?

@Test(expected=ConcurrentModificationException.class) 
//put1 put2 commit1 commit2 
public void test1() { 
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); 
    Transaction txn1 = ds.beginTransaction(); 
    Transaction txn2 = ds.beginTransaction(); 
    ds.put(txn1,new Entity("TestEntity",1)); 
    ds.put(txn2,new Entity("TestEntity",1)); 
    txn1.commit(); 
    txn2.commit(); 
} 

@Test(expected=ConcurrentModificationException.class) 
//put1 commit1 put2 commit2 
public void test2() { 
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); 
    Transaction txn1 = ds.beginTransaction(); 
    Transaction txn2 = ds.beginTransaction(); 
    ds.put(txn1,new Entity("TestEntity",1)); 
    txn1.commit(); 
    ds.put(txn2,new Entity("TestEntity",1)); 
    txn2.commit(); 
} 

@Test(expected=ConcurrentModificationException.class) 
//get1 get2 put1 commit1 put2 commit2 
public void test3() throws InterruptedException, ExecutionException { 
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); 
    ds.delete(KeyFactory.createKey("TestEntity", 1)); 
    Transaction txn1 = ds.beginTransaction(); 
    Transaction txn2 = ds.beginTransaction(); 
    Assert.assertNull(getTestEntity(ds, txn1)); 
    Assert.assertNull(getTestEntity(ds, txn2)); 
    ds.put(txn1,new Entity("TestEntity",1)); 
    txn1.commit(); 
    ds.put(txn2,new Entity("TestEntity",1)); 
    txn2.commit(); 
} 
+2

잠시 동안이 질문은 쓰기 전용 데이터베이스에 관한 것이라고 생각했습니다 .... 나는 당신에게 팔려고했던 실제 실적이 좋은 것을 얻었습니다. :) – Gus

답변

4

귀하는 정확합니다. (MVCC) 일관성은 이 아니며 트랜잭션이 변경 가능한 데이터의 스냅 샷을 관찰하는 첫 번째 이벤트까지에 타임 스탬프가 필요합니다.

생각해보십시오 : 독서가없는 단일 레코드를 변경 한 트랜잭션이 어떻게 일관성을 위반할 수 있습니까? 읽지 않았으므로 본질적으로 아무런 가정도하지 않습니다. 따라서 쓰기/쓰기 충돌로 이어질 수있는 가정은 없습니다.

결말은 당신이 일관성의 안전 혜택을 얻고 있다는 것입니다. 일관성을 유지하기 위해 첫 번째 트랜잭션 읽기를 발행 할 때까지 시간 소인이 필요하지 않습니다.