Django 1.5选择_进行升级被认为是脆弱的设计

2024-06-30 16:52:43 发布

您现在位置:Python中文网/ 问答频道 /正文

Django documentation状态

If you were relying on “automatic transactions” to provide locking between select_for_update() and a subsequent write operation — an extremely fragile design, but nonetheless possible — you must wrap the relevant code in atomic(). Since Django 1.6.3, executing a query with select_for_update() in autocommit mode will raise a TransactionManagementError.

为什么这个被认为是易碎的?我本以为这会导致适当的交易。在


Tags: todjangoinyouforifon状态
3条回答

答案就在拐角处,在select_for_update(emphasis mine)的文档中:

Evaluating a queryset with select_for_update in autocommit mode is an error because the rows are then not locked. If allowed, this would facilitate data corruption, and could easily be caused by calling, outside of any transaction, code that expects to be run in one.

换句话说,在autocommit和{}之间存在矛盾的行为,这可能导致数据损坏。这里是他们第一次提出解决这个问题的django developer's discussion,引用(同样,强调我的):

[...] under Oracle, in autocommit mode, the automatic commit happens immediately after the command is executed and so, trying to fetch the results fails for being done in a separate transaction.

However, with any backend, select-for-update in autocommit mode makes very little sense. Even if it doesn't break (as it does on Oracle), it doesn't really lock anything. So, IMO, executing a query that is a select-for-update in autocommit mode is probably en error, and one that is likely to cause data- corruption bugs.

So I'm suggesting we change the behavior of select-for-update queries, to error out [...] This is a backwards-incompatible change [...] These projects should probably be thankful they were running with a subtle bug that is now exposed but still.

所以这是一个只有Oracle的bug,它揭示了一个与所有后端相关的更深层次的问题,所以他们决定在django中把这个错误作为一个错误。在

另一方面,Atomic只在数据库验证没有错误后才将内容提交给数据库,从而解决了问题。在

Aymeric通过电子邮件澄清说,这种设计是脆弱的,因为它依赖于Django1.5的隐式事务形成的隐式事务边界。在

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

这段代码在简单的情况下工作,但是如果more_code()导致对数据库的写入操作,那么事务将关闭,从而产生意外的行为。在

强制用户指定事务边界也会导致代码更清晰。在

select_for_update不易碎。在

我写道“如果您依赖于“自动事务处理”,那么当您从1.5版本从1.6版本升级到1.5版本时,您需要检查代码。在

如果你不依赖于“自动交易”,甚至如果这个概念没有敲响警钟,那么你就不需要做任何事情。在

正如yuvi的回答所指出的(非常好,谢谢!)Django遇到无效代码时将引发异常。在您看到由select_for_update引发的TransactionManagementError之前,不需要考虑这个问题。在

相关问题 更多 >