django中的嵌套事务?

时间:2009-09-18 09:28:57

标签: django transactions

假设我使用app1.models.ModelOne装饰的保存定义了模型@commit_on_successModelOne.save()中捕获的所有异常都会重新引发。在model_one_instance.save()上正常工作。

但是,在app2中,我需要对ModelOne进行一系列插入,并在其中任何一个失败时回滚所有这些内容。我该如何做到这一点?

使用app2.jobs.do_the_inserts装饰@commit_on_success无效。

2 个答案:

答案 0 :(得分:4)

嵌套事务是特定于数据库的,因此您将失去可移植性。如果您需要,我会考虑做的是更改简单的@commit_on_save以获得更灵活的内容:

def save(commit=True):
  if commit:
    db.start_transaction()
    try:
        self.real_save()
        db.commit_transaction()
    except backend.DatabaseError, e:
        db.rollback_transaction()
        raise e
  else:
    self.real_save()     

否则,您可以运行任意SQL命令,这样您就可以使用后端数据库使用的任何内容调用db.connection.cursor().execute(),可能需要检查不对其他后端执行任何操作,这样您仍然可以使用sqlite进行本地测试。

根据您的应用结构,也可以使用savepoints。我写了一些实用程序,它们做了类似的事情:

  • 开始交易
  • 执行强制命令
  • 启动可选语句:
    • 启动保存点
    • 执行
    • 保存点提交或回滚
  • 更强制SQL
  • 提交

答案 1 :(得分:0)

根据您的DBMS服务器,可能根本不支持嵌套事务。在DBMS中正确实现嵌套事务实际上非常困难,因为最终必须在事务之间共享锁。

但是,您所描述的内容听起来并不像嵌套交易。我不知道django是否支持XA事务,但您所描述的内容可以通过TP监视器体系结构和XA感知DBMS实现(现在大部分都是这样)。

如果您的平台不支持XA事务,则必须对事务进行结构化,以便将存储它们的记录存储在某处。 Fowler的企业应用程序架构模式中描述的“工作单元”模式的某些方面可能为这种子系统的体系结构提供了良好的开端。