django 1.5 select_for_update被认为是脆弱的设计

时间:2014-05-11 10:15:15

标签: python django django-database

Django documentation

  

如果您依靠“自动交易”来提供锁定   在select_for_update()和后续的写操作之间 - 一个   极其脆弱的设计,但仍然可能 - 你必须包装   atomic()中的相关代码。从Django 1.6.3开始,用。执行查询   自动提交模式下的select_for_update()将引发一个   TransactionManagementError。

为什么这被认为是脆弱的?我原以为这会导致正确的交易。

3 个答案:

答案 0 :(得分:9)

select_for_update并不脆弱。

我写了那个"如果你依赖"自动交易""然后,当您从1.5升级到1.5时,需要检查代码。

如果您不依赖&#34;自动交易&#34;,如果概念没有敲响钟声,那么您就不需要做任何事情。< / p>

正如 yuvi 的答案所指出的那样(非常好,谢谢!)Django会在遇到无效代码时引发异常。在TransactionManagementError select_for_update看到{{1}}之前,我们无需考虑这一点。

答案 1 :(得分:4)

答案即将到来,在select_for_update的文档中(强调我的):

  

在自动提交模式下使用select_for_update评估查询集是一个   错误,因为行未被锁定。如果允许,会这样   促进数据损坏,很容易被调用,   在任何事务之外,代码期望在一个事务中运行。

换句话说,autocommitselect_for_update之间存在矛盾的行为,这会导致数据损坏。这是他们首次提出解决这个问题的django developer's discussion,引用(再次强调我的):

  

[...]在Oracle下,在自动提交模式下,自动提交发生   执行命令后立即执行 - 尝试获取   结果无法在单独的事务中完成。

     

但是,任何后端,自动提交模式下的select-for-update   没什么意义。即使它没有破坏(就像它一样   Oracle),它并没有真正锁定任何东西。所以,IMO,执行一个   查询是自动提交模式下的select-for-update可能是en   错误,以及可能导致数据损坏错误的错误。

     

所以我建议我们改变select-for-update查询的行为,   错误[...]这是一个向后不兼容的变化[...]   这些项目应该是值得庆幸的 - 他们正在运行   现在暴露的微妙错误 - 但仍然。

因此,这是一个仅限Oracle的错误,它显示了与所有后端相关的更深层问题,因此他们决定在django中将此错误。

另一方面,

Atomic仅在验证没有错误后才将数据提交到数据库,从而解决了问题。

答案 2 :(得分:3)

Aymeric通过电子邮件澄清这样的设计很脆弱,因为它依赖于Django 1.5的隐式事务形成的隐式事务边界。

select_for_update(...)
more_code()
save()

此代码适用于简单的情况,但如果more_code()导致对数据库的写操作,则事务将关闭,从而产生意外行为。

强制用户指定事务边界也会产生更清晰的代码。