为什么select_for_update只是被不支持它的数据库忽略?

时间:2017-10-26 04:17:52

标签: python sql django sqlite

select_for_update的Django文档说

  

在不支持SELECT的后端上使用select_for_update()...   FOR UPDATE(如SQLite)将无效。 SELECT ... FOR UPDATE   将不会添加到查询中,如果出现错误,则不会引发错误   select_for_update()用于自动提交模式。

这让我觉得这是一个奇怪且有潜在危险的决定,特别是因为select_for_update用于锁定行。如果我编写使用select_for_update的代码,我会依赖它实际上被尊重!如果数据库后端不支持它,我会期望Django要么退回到一个安全但效率低的替代方案,或者,如果不存在,则抛出某种异常。 / p>

在这种情况下,似乎Django可能会突然默默地重新引入竞争条件,只是忽略不受支持的DB上的select_for_update(例如SQLite)。我的直觉说Django不会这样做,并且必须有一些理由为什么不支持它不需要它(也许是不支持使用完整数据库锁定的引擎?)但我可以&#39 ; t似乎在文档中找到了任何具体的东西来支持这个理论。看起来这个问题似乎也不一定是Django所特有的。

这让我对使用select_for_update非常谨慎,尽管它可以很好地解决当前的一些问题。

2 个答案:

答案 0 :(得分:2)

使用允许减少事务隔离以提高并发访问速度的数据库引擎(例如,PostgreSQL,Oracle和MySQL),SELECT FOR UPDATE用于告诉数据库现在读取的行可能是写到以后。这可以避免在并发事务中出现不一致的数据,甚至可以防止在某些情况下发生死锁。

在SQLite中,所有事务are serializable,即它的行为就像整个数据库被锁定在每个事务周围一样。 (在自动提交模式下,每个语句都包含在一个隐式事务中。)

因此SELECT FOR UPDATE即使实现了,也不会实际添加锁定。忽略它对SQLite来说是正确的。

答案 1 :(得分:0)

从这个角度考虑它。

你刚刚从github安装了一个库,想要使用默认的mysqlite设置快速尝试一下 - 但你不能使用它,因为它们碰巧在一个地方使用select_for_update。你是否愿意包装工作(但有可能出现竞争条件)或者你的脸上爆炸?

Django团队做出了许多妥协,以使他们的产品在其支持的所有不同配置中运行。理想情况下,Django应用程序应该可以放入其中任何一个。如果竞争条件成为开发人员的问题,那么在他们意识到他们使用不合适的后端之前不会进行大量研究,并且必须切换到更适合手头任务的那个。 / p>

换句话说,在这种情况下,Django倾向于兼容功能。

  

Django可以通过忽略select_for_update

突然而无声地重新引入

它不会突然引入它们 - 改变数据库后端并不是人们偶然发生的事情 - 而在生产环境中,它通常是一项非常重要的任务。我们不是在这里掷骰子。如果开发人员选择更改数据库,那么他们最好研究该数据库的优缺点 - 并对其进行测试。

相关问题