7

우리는 SQLAlchemy 선언 기반을 사용하고 있으며 트랜잭션 수준을 격리하려는 방법이 있습니다. 설명하기 위해 데이터베이스에 동시에 쓰는 두 개의 프로세스가 있으며 트랜잭션에서 논리를 실행해야합니다. 기본 트랜잭션 격리 수준은 READ COMMITTED이지만 SERIALIZABLE 격리 수준을 사용하여 코드를 실행할 수 있어야합니다.PostgreSQL 용 SQLAlchemy에서 트랜잭션 격리 수준을 어떻게 설정합니까?

SQLAlchemy를 사용하여 어떻게 이루어 졌습니까? 지금은 기본적으로 SQLAlchemy의 선언적 기반을 상속 한 모델을 기본적으로 트랜잭션 방식으로 호출해야하는 모델을 사용합니다.

from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT 
from psycopg2.extensions import ISOLATION_LEVEL_READ_COMMITTED 
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE 

class OurClass(SQLAlchemyBaseModel): 

    @classmethod 
    def set_isolation_level(cls, level=ISOLATION_LEVEL_SERIALIZABLE): 
     cls.get_engine().connect().connection.set_isolation_level(level) 

    @classmethod 
    def find_or_create(cls, **kwargs): 
     try: 
      return cls.query().filter_by(**kwargs).one() 
     except NoResultFound: 
      x = cls(**kwargs) 
      x.save() 
      return x 

트랜잭션 격리 수준을 사용하여이를 호출하기 위해이 작업을 수행하고 있지만 예상대로 수행하지 않습니다. 격리 수준은 여전히 ​​postgres 로그에 표시된 것으로부터 READ COMMITTED입니다. 누군가 내가 잘못한 것을 알아내는 데 도움이 될 수 있습니까?

나는 분리 레벨은, 예를 들어, 트랜잭션 내에서 설정 SQLAlchemy의 0.5.5

class Foo(OurClass): 

    def insert_this(self, kwarg1=value1): 
     # I am trying to set the isolation level to SERIALIZABLE 
     try: 
      self.set_isolation_level() 
      with Session.begin(): 
       self.find_or_create(kwarg1=value1) 
     except Exception: # if any exception is thrown... 
      print "I caught an expection." 
      print sys.exc_info() 
     finally: 
      # Make the isolation level back to READ COMMITTED 
      self.set_isolation_level(ISOLATION_LEVEL_READ_COMMITTED) 

답변

7

: psycopg2

은 "파라미터 isolation_level"create_engine() 에 인수를 사용하고 사용하시기 바랍니다 0.6.4까지 latest tip of SQLAlchemy 가 해제되고, 거기로 격리 수준과 관련하여 최근에 수정 된 버그 ( )가 수정되었습니다. 대신 그들이 만든 모든 연결에 최대 set_isolation_level을 설정하는 PoolListener를 사용 을 거라고 -

아래이 접근 방식은 는 쿼리에 사용 늦은 동일한 연결에 영향을주지 않습니다.

+3

'create_engine()'에 대한'isolation_level' 인수는 주 연결 관리자에만 영향을 미치므로 각 연결마다 격리 수준을 얻는 것처럼 보입니다. 세션/연결 단위로 연결 풀링과 호환되는 방법을 찾아 냈습니까? 원래의 질문은 특정 방법으로 만 원했던 것처럼 보였습니다. – Russ

-3

을 사용하고 있습니다 PostgreSQL doc에서

try: 
    Session.begin() 
    Session.execute('set transaction isolation level serializable') 
    self.find_or_create(kwarg1=value1) 
except: 
    ... 

: SET 트랜잭션이 이전 START의 TRANSACTION없이 실행 또는 트랜잭션이 즉시 종료됩니다 이후로는 아무런 영향이없는 것으로 나타납니다 BEGIN 경우

.

마이클 바이엘, SQLAlchemy의 메인테이너에서
+0

내일 답변을 테스트하고 작동한다면 이것을 받아 들일 것입니다. –

+0

답변이 작동하지 않습니다. Michael Bayer에 따르면 트랜잭션 격리 수준이 나중에 쿼리에 사용되는 동일한 연결에 영향을 미치지 않는 것처럼 보입니다. –

+0

Michael Bayer의 의견은 내 코드가 아니라 귀하의 코드에 관한 것이라고 생각합니다. 차이점은 트랜잭션을 시작하기 전에 격리 수준을 설정한다는 것입니다. 코드가 작동하지 않는다고 주장하기 전에 실제로 코드를 해봤습니까? – sayap