Django最佳实践-确保在执行业务逻辑时具有原子性

3

我正在对一些Python/Django应用程序中的旧代码进行重构,寻求关于在SQL数据库上执行操作的样式/最佳实践建议。

目前我正在尝试重新编写以下代码:

def fun():
  try:
    with transaction.atomic():
      # query DB

      # do business logic

      # update DB entries with new values
  except:
    # handle exception

事情是这样的,在我的查询和更新之间有相当数量的业务逻辑。但我觉得在事务中定义为另一个缩进/即额外代码似乎不合理。理想情况下,我希望清理一下,并仅作为原子性执行某些操作。我想这实际上并没有减少代码行数,但我很好奇 transaction.atomic() 到底完成了什么任务?
根据我对原子性的理解,读操作并不会实际影响数据存储器的状态,所以我不确定最初的读操作是否应该放在 atomic() 下面。
提前致谢。
1个回答

3
如果读取只是普通的 SELECT 语句,并且您正在使用默认的 READ COMMITTED 事务隔离级别,而更新是单个 SQL 语句,则您是正确的。
但是:
- 如果有多个数据修改语句(例如,您在多个表中修改行),则可能必须使用事务,以便永远不会执行其中一个语句。 在这种情况下,最好在修改数据之前立即开始事务。
- 对于隔离级别 REPEATABLE READ 或以上级别,必须在事务中包含 SELECT 语句,因为当事务中的第一个 SQL 语句执行时,数据库的“快照”(应用于该事务的数据库状态)被记录下来。 您希望您的 UPDATE 看到与您的 SELECT 相同的数据库状态。
- 如果 SELECT 带有 FOR UPDATE 子句,则实际上会锁定表行以防止并发修改。在这种情况下,需要将 SELECT 放在与数据修改相同的事务中,因为锁定将在事务结束时释放。
总之,将数据库事务保持尽可能简短是最好的做法。这减少了死锁的风险并使模式更改变得轻松。

谢谢,根据您的见解,我现在有一个如何继续的想法。 - Ethan Fox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接