【问题标题】:Django request transactions don't completely rollback after save() called. TransactionMiddleware not behaving as expected调用 save() 后,Django 请求事务不会完全回滚。 TransactionMiddleware 未按预期运行
【发布时间】:2011-11-23 00:23:49
【问题描述】:

my previous question 开始,我正在使用带有 InnoDB 引擎的 MySQL,并设置了一个简单的测试表。当我运行以下代码时:

c.execute("""insert into test(text) values('test1')""")
conn.commit()
c.execute("""insert into test(text) values('test2')""")

# Raise an exception to simulate an error
raise Exception('spam', 'eggs')

c.execute("""insert into test(text) values('test3')""")
conn.commit() 

正如预期的那样,我在数据库中看到一个仅针对 test1 的条目。

在Django中创建相关模型类并运行等效代码后,(我在settings.py中指定了TransactionMiddleware):

def transaction_test(request):
    t1 = Test(text='test1')
    t2 = Test(text='test2')
    t1.save()

    # Raise an exception to simulate an error
    raise Exception('spam', 'eggs')    

    t2.save()
    return render_to_response('index.html')

然后我仍然在表中看到“test1”的条目,而根据 TransactionMiddleware 文档中给出的描述,我预计整个事务都会回滚,包括“test1”的保存

还有其他人看过吗?我还缺少其他 Django 设置吗?

【问题讨论】:

  • 你从哪里开始交易?

标签: django transactions rollback


【解决方案1】:

确定test 表正在使用innodb 引擎吗?

我可以相信您没有正确设置事务中间件,但如果 transaction.commit_on_success 装饰器不起作用,我觉得该表可能正在使用 MyISAM

您可以在mysql shell中使用以下命令检查引擎:

show table status where name="test";

【讨论】:

  • 是的 - 绝对肯定 InnoDB 被设置为数据库引擎。这就是我包含显示原始 SQL 的 sn-p 的原因。当我使用 MyISAM 引擎执行这段代码时,它向数据库提交了两个条目;当我切换到 InnoDB 时,它只显示一个条目,回滚了事务。但是,尝试对 Django 执行相同操作时,它总是 提交保存操作,而不管我使用哪个数据库引擎。无论如何,我运行了上面的 SQL,它清楚地显示 InnoDB 作为“测试”表的引擎
  • 好的,我第一次看错了你的原始 SQL sn-p。我有一个最后的想法。 Django 将为测试模型创建一个名为myapp_test 的表,而不是test。你是用 SQL 和 Django 测试同一张表吗?
  • 我做了相反的事情:首先我在数据库中创建了表(指定 innodb 作为引擎),然后运行 ​​inspectdb 来生成 Django 模型。在这种情况下,Django 是否仍会在我需要追踪的某个地方创建另一个内部表(并检查它是否使用 InnoDB)?
  • 这里是关于 table names 的文档。您可以使用 db_table 元选项指定 Django 将使用的表名。 inspectdb 似乎确实正确指定了 db_table 元选项,所以这可能不是问题。
  • 我刚刚完成并将所有 django 表也设置为 innodb。并验证了 db_table 元数据。但不好 - 事务在异常后仍然没有回滚
【解决方案2】:

如果你使用的是 django.test.TestCase 而不是 django.test.TransactionTestCase,那么整个操作被包装在一个回滚的事务中;除了 MySQL 可能会在锁定表时提交,这会使事情变得混乱。我通过将超类切换到 TransactionTestCase 解决了类似的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 2018-09-15
    • 2018-05-17
    • 2014-02-19
    • 1970-01-01
    相关资源
    最近更新 更多