2012-08-10 2 views
4

켜져와 행 우리는 이전의 MySQL을 통해 원활하게 달린 Grails의 2.0 응용 프로그램을 개발 PostgreSQL을에 존재하는 동안 (무작위) 널 (null)Grails의 : 선택 반환 연결 풀링

우리는 PostgreSQL을 전환하기 위해 관리자에 의해 요청 된 적이있는 그들은 우리는 지금 우리에게 문제를 일으키는 것을 포함하여 응용 프로그램에 새로운 기능을 잔뜩 추가 한

선호 : 비동기 타사 웹 서비스 요청

그래서, 우리는 도메인 객체 생성이를, 현실을 부르 자 문제. afterInsert 클로저를 사용하면 나중에 외부 웹 서비스 호출 결과를 저장하기 위해 Resource이 만들어집니다.

class Question implements Serializable { 

    static hasMany = [resources: Resource] 

    static constraints = { 
     resources(nullable: true) 
    } 
    def afterInsert() { 
     Resource.withNewSession { 
      Resource txt = Resource.create(null) 
      this.addToResources(txt) 
     } 
    }   

    Resource retrieveResource(){ 
     return this.resources.find{ it instanceof Resource } 
    }   

    static Question create(Map params) throws SaveDomainException { 
     //question creation 
    }  
} 

우리는 이런 질문을 만듭니다

//first we create question and save it 
def question = Question.create(params) 
question.save(flush:true, insert:true) 
getThirdPartyService().doCallAsync((int)req.retrieveResource().id) 

이이 두려워한 "최대 절전 모드 세션되지 않도록 실행 프로그램을 통해 얻은 ExecutorService이 (플러그인을 Grails의 급부상하는 방법 doCallAsync으로 ThirdPartyService - Thread "problem) 위의 그림과 같이 얻은 Id가 간단한 Resource.get(res_id)을 실행하는

문제는 PostgreSQL 및에서 발생합니다.에 DataSource.groovy이있는 경우 get은 null을 반환하고 리소스 객체를 상주시킵니다.

우리는 선택 항목이있는 get(id), findById(id)executeQuery의 세 가지 요청을 테스트했습니다.

같은 방법으로 위의 3 줄을 사용하면 이상한 결과가 나오는 경우가 있습니다. 3 개 중 하나만 null을 반환하거나 3 개가 null을 반환하거나 아무 것도 반환하지 않습니다 (예상되는 동작입니다).

PostgreSQL 쿼리 로그가 최대 절전 모드 캐시 문제인지 여부를 확인했습니다 3 개의 요청은 모두 로그에 나타나므로 최대 절전 모드가 데이터베이스를 찾을 때마다 최대 절전 모드가됩니다. 올바른 ID를 가진 리소스의 삽입을 확인한 다음 커밋과 3 개의 선택 (올바른 리소스 ID와 함께 제공됨)을 참조하십시오.

누가 더 테스트 할 것인지에 대한 힌트가 있습니다. 이 버그는? (우리는 연결 풀을 바꿔 보려고했습니다. 행운이 없음)

마지막으로, 요청 전에는 Thread.sleep(1000) (테스트 목적으로 만 사용하고 테스트 목적으로 만 사용합니다.)을 추가하면 모두 원활하게 실행됩니다. 따라서 포스트 그레스 프로세스 사이에 가시성 문제가있는 것 같지만 해결 방법에 대한 단서가 없습니다

답변

2

이 문제를 연구하고 잘 제시된 질문으로 작성했습니다 중요한 기록을 남기지 않습니까?

나는 당신이 당신의 저장과 async get 사이에 중첩 된 트랜잭션을 가지고 있다고 생각할 것이다. 저장이 커밋되지 않았거나 가져 오기 전에 저장이 발생하기 전에 일관된 스냅 샷이 표시됩니다. 당신이 연결을 구별하는 로깅 활성화 프로세스 ID 또는 다른 방법이 단지에서 발생하는 문을 주문 무엇을 볼 수 있는지 확인


편집 :. 트랜잭션 스냅 샷 타이밍처럼 보인다.

PostgreSQL에서 모든 명령문은 트랜잭션 내에 있습니다 (암시 적이거나 하나의 명령문 만 가능).

기본 모드는 "읽기 커밋"입니다. 즉, 트랜잭션 중에 커밋 된 것을 볼 수 있습니다.

트랜잭션 시작시 데이터베이스의 고정 된 스냅 샷을 (대부분) 볼 수있는 "직렬화 가능"레벨 옵션이 있습니다.

자세한 내용은 the docs을 참조하십시오.

두 개의 psql 콘솔을 열고 하나에서 커밋하고 다른 격리 수준에서 다른 것을 선택하면 몇 가지 변형을 시험해보십시오. 라이브 시스템에서 어떤 일이 일어나고 있는지 확인할 수 있어야합니다.

+0

그래, 저장이 실제로 클라이언트에게 확인되기 전에 스냅 샷을 잡은 트랜잭션에서 'SELECT'가 실행되는 경쟁 조건처럼 보일 것입니다. – kgrittn

+0

응답 해 주셔서 감사합니다. 예, 로깅에서 process-id가 활성화되어 있고 올바른 것입니다. 'insert' +'commit'은 3 개의'select' 프로세스 중 다른 프로세스에서 실행됩니다. 스냅 샷이 동기화되었는지 어떻게 확인할 수 있습니까? 이 동기화를 강제 할 수 있습니까? – user1590586

+0

@ user1590586 - 편집 된 답변보기 –