Database 我应该在事务中包括选择项吗?
当使用数据库事务对多个更新进行分组时,我是否也应该在事务中包含选择?例如,假设我:Database 我应该在事务中包括选择项吗?,database,django,postgresql,transactions,Database,Django,Postgresql,Transactions,当使用数据库事务对多个更新进行分组时,我是否也应该在事务中包含选择?例如,假设我: 记录 使用记录中的数据检查该记录的编辑权限 更新一些记录 更新一些其他记录 我应该在“获取记录”阶段之前启动事务,还是在更新前后启动事务 我使用的是Postgres/Djangotransaction.atomic(),但我认为这并不重要。简短的版本:“这取决于” 长版本: 如果您正在执行读-修改-写循环,那么它不仅必须在事务中,而且必须选择。。。对于更新您以后打算修改的任何记录。否则,您将面临写操作丢失的风险,
transaction.atomic()
,但我认为这并不重要。简短的版本:“这取决于”
长版本:
如果您正在执行读-修改-写循环,那么它不仅必须在事务中,而且必须选择。。。对于更新
您以后打算修改的任何记录。否则,您将面临写操作丢失的风险,您将在读取记录和编写更新之间覆盖其他人所做的更新
SERIALIZABLE
事务隔离也有助于实现这一点
您确实需要了解并发和隔离。不幸的是,唯一简单、简单的“justdox”答案是通过锁定所有涉及的表来开始每个事务。大多数人不想那样做
我建议读一读(或两读,或三读,或四读——这是硬材料)。使用并发psql
会话(多个终端)进行试验,以创建竞争条件和冲突 理想情况下(如果可能的话),您可以在一个事务中完成所有四个步骤(在一个事务中自动完成)
这仍然不能排除比赛条件,只是使其不太可能,因为SELECT。。对于更新
和以后的更新将最小化。(是的,在高并发访问下,您仍然应该使用来对抗竞争条件。)
这不是Django这样的web框架的典型(低效)方法。但这是最好的方法。它通过多种方式优化性能:
- 减少到db服务器的往返次数(可能是最重要的)
- 最小化锁定时间
- 允许Postgres优化查询
时,选择。。对于数据修改CTE中的更新
,请注意,这也不会按预期锁定行
数据修改CTE的代码示例:
Django用户注意事项:
SELECT。。。对于更新
,可通过Django的选择更新
()@ScottStafford。。。但不幸的是,选择。。。对于共享
,或PostgreSQL的选择。。。对于密钥共享
/对于密钥更新
。因此,为了确保遵循Django角度,像MyObject.objects.get(pk=5)
这样的调用不会锁定任何东西,无论是否在事务.atomic()中。要做到这一点,我需要在事务.atomic()
内部,并使用类似MyObject.objects的表单。选择_for_update().get(pk=5)
,以确保在事务结束之前不能更改MyObject 5。非常有趣。在我的例子中,我可以多次往返数据库,以换取代码的可维护性,并将授权逻辑保留在代码中的一个位置。我正在寻找事务正确性——尽管ORM在这里玩游戏。另外,CTE让我害怕。@ScottStafford:SQL或PL/pgSQL服务器端函数可能不是那么可怕,具有类似的好处。。。