2010-08-19 166 views
7

我们正在使用SQLAlchemy声明基础,并且我有一个方法要隔离事务级别。为了解释,有两个进程同时写入数据库,我必须让他们在事务中执行逻辑。默认事务隔离级别是READ COMMITTED,但我需要能够使用SERIALIZABLE隔离级别执行一段代码。如何在SQLAlchemy for PostgreSQL中设置事务隔离级别?

这是如何使用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

从迈克尔·拜尔的SQLAlchemy的维护者:

请使用 “ISOLATION_LEVEL” 参数create_engine() 和使用latest tip of SQLAlchemy 直到0.6.4被释放,因为有一个 psycopg2 - 关于隔离级别最近修复的特定错误 。

你有下面的方法不 影响是 后来用于查询相同的连接 - 你会 改用PoolListener,设置所有连接 高达 作为set_isolation_level创建它们。

+3

似乎'create_engine()'的'isolation_level'参数仅影响主连接管理器,因此您可以在每个连接上获得该隔离级别。你有没有想出一个连接池兼容的方式来实现这个每会话/连接的基础?你原来的问题似乎只是你想要某种方法。 – Russ 2010-12-14 02:58:43

-3

隔离级别被设置在一个事务中,例如

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

PostgreSQL doc

如果SET交易没有启动之前事务执行或BEGIN,它会出现没有任何效果,因为该交易将立即结束。

+0

我会明天测试你的答案,并接受它,如果它的工作:)我有一种感觉它会。 – 2010-08-23 02:40:53

+0

你的回答不起作用。根据Michael Bayer的说法,它看起来像事务隔离级别不会影响稍后用于查询的同一连接。 – 2010-08-24 01:54:09

+0

我相信Michael Bayer的评论是关于你的代码的,而不是我的。区别在于你在开始事务之前设置了隔离级别。声称它不起作用之前,你真的尝试过这些代码吗? – sayap 2010-08-27 12:13:22

相关问题