交易内的交易

blu*_*oot 8 python database postgresql sqlalchemy

我想知道在另一个内部打开交易是否安全并受到鼓励?

我有一个方法:

def foo():
    session.begin
    try:
          stuffs
    except Exception, e:
         session.rollback()
         raise e
    session.commit()
Run Code Online (Sandbox Code Playgroud)

以及在事务中调用第一个的方法:

def bar():
    stuffs
    try:
         foo()   #<<<< there it is :)
         stuffs
    except Exception, e:
        session.rollback()
        raise e
    session.commit()
Run Code Online (Sandbox Code Playgroud)

如果我在foo方法上获得异常,那么所有操作都将被回滚?其他一切都会好起来的吗?谢谢!!

Ant*_*sma 18

在SQLAlchemy中嵌套事务有两种方法.一个是虚拟事务,其中SQLAlchemy会跟踪您已发出的开始数量,并仅在最外层事务提交时发出提交.然而,回滚立即发布.因为事务是虚拟的 - 即数据库不知道嵌套,所以在回滚之后您无法对该会话执行任何操作,直到您回滚所有外部事务.允许使用虚拟事务subtransactions=Truebegin()调用添加参数.此功能的存在允许您在函数内部使用事务控制,如果您在事务内部,则可以相互调用而不保持跟踪.为了使它有意义,配置会话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')
Run Code Online (Sandbox Code Playgroud)

在PostgreSQL SQLAlchemy嵌套事务上运行得很好.