2010-11-26 5 views
4

나는 다음과 같은 쿼리를 반복하고 수행하는 데몬에 스레드가 :Sqlalchemy orm 세션에서 올바르게 캐싱을 사용하지 않도록 설정하는 방법?

절전 방법은 단지 구성 시간이 스레드 및 메인 루프에 return 문 반환의 실행을 중지
try: 
     newsletter = self.session.query(models.Newsletter).\ 
       filter(models.Newsletter.status == 'PROCESSING').\ 
       limit(1).one() 
    except sa.orm.exc.NoResultFound: 
     self.logger.debug('No PROCESSING newsletters found. Sleeping...') 
     self.sleep() 
     return 
    # (...) more code to do with found newsletter 

. 그러나 데몬이 실행되는 동안 뉴스 레터의 상태를 'PROCESSING'으로 변경하면 아무 일도 일어나지 않습니다. 쿼리는 여전히 NoResultFound를 발생시킵니다. 그러나 데몬을 다시 시작하면 뉴스 레터를 찾을 수 있습니다. 따라서이 쿼리의 결과는 캐시되어야합니다. 캐시를 무효화하려면 어떻게해야합니까? session.expire_all()이 작동하지 않습니다. 모든 반복마다 새 Session() 객체를 만들 수도 있지만 시스템 리소스와 관련하여 좋은 접근 방식인지는 알 수 없습니다.

+2

나쁜 가정. 데이터베이스가이 두 트랜잭션을 어떻게 직렬화하는지 알고 있습니까? 이 두 트랜잭션에 어떤 데이터베이스 잠금이 관련되어 있는지 알고 있습니까? SQLAlchemy 캐시를 어떻게 알 수 있습니까? 쿼리가 잘못된 잠금을 제거하기 때문에 쿼리가 완료 될 때까지 업데이트를 방해하는 데이터베이스 잠금이 될 가능성이 있습니다. 캐싱에 대한 증거가 있습니까? 아니면 추측입니까? –

+0

나는 증거가 없다. 그냥 추측. 어쩌면 캐싱이 다른 곳에서 이루어질 수도 있습니다. 롤백() 사용은 여기에서 작동하는 것 같습니다. – zefciu

+0

** 캐싱이 아닌 ** 잠금 인 경우가 많습니다. –

답변

5

SQLAlchemy doesn't cache 그 자체. 명시 적으로 캐시를 구현하지 않는 한 like this one.

sessionmakerecho=True을 입력하고 logging output을 조사하십시오.

+0

전달 중 echo = True가 작동하지 않습니다. 또한 sqlalchemy.engine logger에서 로깅을 설정하려고 시도했지만 작동하지 않았습니다. – zefciu

+0

로깅을 활성화 했습니까? – knitti

+0

app-wide 로깅을 활성화해야 할 수도 있습니다. https://gist.github.com/aphillipo/25ae5456cf1fe7fed1a5 – pip

1

흠 이미 답변을 찾았습니다. session.commit()을 명시 적으로 수행하여 업데이트하거나 세션에서 autocommit = True로 설정할 필요가 있습니다 (예 : sessionmaker). 내가

그래서이는 방식으로 거래 코드에서

3

문제를 작동 단지 것 같다 캐싱 문제가되지 않습니다여 session.commit() 방법을 테스트하지 않았습니다 그러나

sessionmaker(bind=self.engine, autocommit=True) 

REPEATABLE READ isolation level을 기본값으로 사용하기 때문에 commit() 또는 rollback()을 호출하거나 Xeross가 제안한대로 autocommit=True을 사용하거나 수동으로 격리 수준을 변경하지 않으면 쿼리가 동일한 결과를 반환합니다.

예, SQLAlchemy는 ORM 패턴에 각 ID에 대해 단일 개체가 필요하기 때문에 매핑 된 개체 (쿼리 결과 아님)를 캐시합니다. 기본적으로 SQLAlchemy는 약한 ID 맵을 캐시로 사용하므로 참조가 남아 있지 않을 때 객체는 자동으로 세션에서 제거됩니다. 후속 쿼리는 캐시 된 객체의 상태를 새 데이터로 업데이트하므로이 캐시에 대해 걱정할 필요가 없습니다.

1

은 진정한 = 자동 커밋 =이 True 및 expire_on_commit 사용하지 않는

for state in self.identity_map.all_states(): 
    state.expire(state.dict, self.identity_map._modified) 

할 수 있습니다 : 쿼리 후 : db.session.commit() 당신의 부분에

관련 문제