我们正在使用SQLAlchemy声明基础,我有一个方法,我想隔离事务级别。为了解释,有两个进程同时写入数据库,我必须让它们在事务中执行它们的逻辑。默认事务隔离级别是READ COMMITTED,但我需要能够使用SERIALIZABLE隔离级别执行一段代码。
如何使用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)
答案 0 :(得分:9)
来自MichaelAlber,SQLAlchemy的维护者:
请使用“isolation_level” create_engine()的参数 并使用latest tip of SQLAlchemy 直到0.6.4被释放,因为有 最近修复的psycopg2特定错误 关于隔离级别。
你下面的方法没有 影响相同的连接 后来用于查询 - 你 而是使用设置的PoolListener 所有的set_isolation_level 连接,因为它们被创建。
答案 1 :(得分:-2)
隔离级别在事务中设置,例如
try:
Session.begin()
Session.execute('set transaction isolation level serializable')
self.find_or_create(kwarg1=value1)
except:
...
如果在没有事先START TRANSACTION或BEGIN的情况下执行SET TRANSACTION,它将显示无效,因为交易将立即结束。