我想知道在另一个内部打开交易是否安全并受到鼓励?
我有一个方法:
def foo():
session.begin
try:
stuffs
except Exception, e:
session.rollback()
raise e
session.commit()
以及在事务中调用第一个的方法:
def bar():
stuffs
try:
foo() #<<<< there it is :)
stuffs
except Exception, e:
session.rollback()
raise e
session.commit()
如果我在foo方法上获得异常,那么所有的操作都将是 回滚?其他一切都会好起来的吗? 谢谢!
答案 0 :(得分:18)
在SQLAlchemy中嵌套事务有两种方法。一个是虚拟事务,其中SQLAlchemy会跟踪您已发出的开始数量,并仅在最外层事务提交时发出提交。然而,回滚立即发布。因为事务是虚拟的 - 即数据库对嵌套一无所知,所以在回滚之后您无法对该会话执行任何操作,直到您回滚所有外部事务。允许使用虚拟事务向subtransactions=True
调用添加begin()
参数。此功能的存在允许您在函数内部使用事务控制,如果您在事务内部,则可以相互调用而不保持跟踪。要使其有意义,请使用autocommit=True
配置会话,并始终在事务处理函数中发出session.begin(subtransactions=True)
。
嵌套事务的另一种方法是使用真正的嵌套事务。它们使用保存点实现。如果回滚嵌套事务,则回滚该事务中所做的所有更改,但外部事务仍然可用,并且外部事务所做的任何更改仍然存在。使用嵌套事务问题session.begin(nested=True)
或session.begin_nested()
。所有数据库都不支持嵌套事务。 SQLAlchemy的测试套件库配置函数sqlalchemy.test.requires.savepoints
说明了这个支持:
emits_warning_on('mssql', 'Savepoint support in mssql is experimental and may lead to data loss.'),
no_support('access', 'not supported by database'),
no_support('sqlite', 'not supported by database'),
no_support('sybase', 'FIXME: guessing, needs confirmation'),
exclude('mysql', '<', (5, 0, 3), 'not supported by database')
在PostgreSQL上SQLAlchemy嵌套事务工作正常。
答案 1 :(得分:0)
你不能,PostgreSQL不支持子交易。您可能想要使用保存点,但那就是其他内容。
答案 2 :(得分:0)
在PostgreSQL上嵌套的事务工作得很好。
好吧,你不会得到错误(只是一个警告),这是真的。但是你不能提交内部事务并回滚外部事务,外部事务也会回滚内部事务。
BEGIN;
INSERT INTO x(foo)VALUES('John');
BEGIN; - 警告!
INSERT INTO y(bar)VALUES('Jane');
COMMIT; - 提交内部交易
ROLLBACK; - 将回滚两个插入,而不仅仅是第一个,即表“x”
中的插入
据我所知,Oracle是少数拥有此选项的人之一。