当前位置: 首页 > 面试题库 >

Django嵌套事务-'ith transaction.atomic()'-寻求澄清

谷梁英资
2023-03-14
问题内容

在Django嵌套事务中-‘ith
transaction.atomic()’
。考虑到这一点,问题是…

def functionA():
    with transaction.atomic():
        #save something
        functionB()

def functionB():
    with transaction.atomic():
        #save another thing

如果functionB失败并回滚,是否functionA也会回滚?

凯文·克里斯托弗·亨利(Kevin Christopher Henry)回答:“是的,如果这两个功能中的任何一个发生异常,它们都将被回滚。”
然后,他引用docs,其中指出:

原子块可以嵌套。在这种情况下,当内部块成功完成时,如果稍后在外部块中引发异常,则其效果仍然可以回滚。

该文档引用似乎并未解决原始问题。该文档说,当INNER
BLOCK(即functionB)成功完成时,如果OUTER块(即functionA)引发异常,则其效果仍然可以回滚。但是问题是相反的情况。问题问,如果INNER块(functionB)失败,OUTER块(functionA)是否回滚?此文档引用无法解决该情况。

但是,在文档的更下方,我们看到了这个示例…

from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()

…此评论之后…

在此示例中,即使generate_relationships()由于破坏完整性约束而导致数据库错误,您也可以在中执行查询add_children(),并且来自create_parent()那里的更改仍然存在。

如果我在看文档正确它说调用generate_relationships()(这类似于调用functionB在原来的问题)可能会失败,并在所做的更改create_parent(),并add_children()会被提交到数据库。这似乎与凯文·克里斯托弗·亨利的回答相矛盾。

我是Django和stackoverflow的新手,所以我对阅读文档没有足够的信心,但是这似乎与这两个答案都相矛盾。我正在寻找经验更丰富的人做些澄清。非常感谢。


问题答案:

下面是一些伪代码嵌套事务块和数据库操作XY以及Z

with transaction.atomic():
    X
    with transaction.atomic():
        Y
    Z

如果X引发异常,那么显然所有操作都没有机会首先提交。

如果Y引发异常(您所提到的问题是“您提到的问题”),那么外部块也会回滚。就其本身而言,这与嵌套事务没有任何关系,这是因为Python异常冒出来了。外部块将被异常退出,该异常始终会导致回滚。不管是什么原因导致异常,这都是事实。

非显而易见的情况是Z引发异常时发生的事情,这就是为什么文档对此进行了特别注意。作为参照,二者XY将回滚:

当内部块成功完成时,如果稍后在外部块中引发异常,则其效果仍然可以回滚。

现在,还可以捕获嵌套操作引发的异常。

with transaction.atomic():
    X
    try:
        with transaction.atomic():
            Y
    except IntgrityError:
        pass
    Z

在这种情况下,如果Y引发异常,则内部块将回滚(因为它退出并带有异常),而外部块则不会回滚(因为它没有)。

这与您提到的两个答案中的任何一个都不矛盾,因为这些答案针对的是特定的问题(带有代码示例),这些问题不涉及捕获任何异常。

无论如何,感谢您的反馈和提供更全面答案的机会。



 类似资料:
  • 环境: 我们有一个应用程序部署在 JBoss 4.2.3.GA 服务器中,它使用Hibernate 3.4 和 JTA 1.0。 有一个导入器创建或更新某些实体,然后导入一些数据。由于多种原因,大部分导入是在新事务中完成的,在每个事务中,在外部事务中创建/更新的实体可能会再次更新。 调用序列类似于以下伪代码: 服务1: 服务2: 问题: 现在的问题是,我们最终会遇到一个竞争条件,有几个事务试图锁定

  • 据我所知,当您尝试在提交前一个事务之前开始一个事务时,会发生这种异常。然而,我不明白为什么在我的情况下会有这种例外。 我有一个Web应用程序与以下servlet: 这是我的Compte对象: 这是我的DAO的接口: 这就是它的实施: 另外,这是我的Spring配置: 关联的应用程序。属性文件包含以下行: 最后,我有以下servlet过滤器,从这里开始事务: 这是在网络上映射的。如下所示的xml文件

  • 问题内容: 我正在研究应用数据库架构更新的脚本。我已经使用start transaction / commit设置了所有的SQL更新脚本。我在命令行上将这些脚本传递给psql。 现在,我需要在一个事务中同时应用多个脚本。到目前为止,我想出的唯一解决方案是从原始脚本集中删除启动事务/提交,然后将它们卡在新的启动事务/提交块中。我正在编写perl脚本来即时执行此操作。 实际上,我想要嵌套事务,但是我无

  • 我很难清楚地理解MySQL5.6使用/r/t memcache引入了什么。 按照我的理解,memcache本身本质上是一个巨大的、共享的、驻留内存的哈希表,由服务器memcached管理。特别是,它对持久数据存储一无所知,也不提供这方面的服务。它只知道键和值(像Perl散列)。 我认为MySQL5.6引入的是NoSQL API,mySQL客户端可以通过键而不是通过SELECT语句从mySQL服务器

  • 我有一种情况,我必须提交一部分代码作为它自己的事务。 我已经创建了一个表: 以及plpython3u语言中的函数: 第一种情况: 表中的条目正确:1、2、4 第二种情况: 表中的值未填充 我希望或应该添加到表 中,但出乎意料的是没有插入任何值。我想象函数打开了一个新的子事务,它不应该依赖于父事务。如果我是对的,请告诉我。 Postgres中是否存在自主交易?或者我必须修改我的plpython3u函

  • 如果一个服务方法被标记为具有传播嵌套的,并且在它内部有许多对其他方法的调用,那么这些方法中的每一个都将使用自己的会话?它应该表示多个连接到db,只有一个方法调用no?