交易内的交易

时间:2010-02-25 19:28:45

标签: python database postgresql sqlalchemy

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

我有一个方法:

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方法上获得异常,那么所有的操作都将是 回滚?其他一切都会好起来的吗? 谢谢!

3 个答案:

答案 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是少数拥有此选项的人之一。