Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 我应该在事务中包括选择项吗?_Database_Django_Postgresql_Transactions - Fatal编程技术网

Database 我应该在事务中包括选择项吗?

Database 我应该在事务中包括选择项吗?,database,django,postgresql,transactions,Database,Django,Postgresql,Transactions,当使用数据库事务对多个更新进行分组时,我是否也应该在事务中包含选择?例如,假设我: 记录 使用记录中的数据检查该记录的编辑权限 更新一些记录 更新一些其他记录 我应该在“获取记录”阶段之前启动事务,还是在更新前后启动事务 我使用的是Postgres/Djangotransaction.atomic(),但我认为这并不重要。简短的版本:“这取决于” 长版本: 如果您正在执行读-修改-写循环,那么它不仅必须在事务中,而且必须选择。。。对于更新您以后打算修改的任何记录。否则,您将面临写操作丢失的风险,

当使用数据库事务对多个更新进行分组时,我是否也应该在事务中包含选择?例如,假设我:

  • 记录
  • 使用记录中的数据检查该记录的编辑权限
  • 更新一些记录
  • 更新一些其他记录
  • 我应该在“获取记录”阶段之前启动事务,还是在更新前后启动事务

    我使用的是Postgres/Django
    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服务器端函数可能不是那么可怕,具有类似的好处。。。