【问题标题】:Incrementing a database counter concurrently同时增加数据库计数器
【发布时间】:2018-09-23 01:45:49
【问题描述】:

从我在 PostgreSQL documentation 中读到的内容,似乎查询像

UPDATE accounts SET balance = balance + 100 WHERE account_id = 12345

是原子的,可以安全地并发执行。仅当更新单个整数列时才会出现这种情况?在我的 Django 应用程序中,我有一个这样的查询(由 ORM 生成):

UPDATE "mytable" SET "counter" = ("mytable"."counter" + 1), 
  "owner" = NULL, "updated" = '2018-04-12T12:53:17.826257+00:00'::timestamptz
WHERE "mytable"."id" = 27; args=(1, datetime.datetime(2018, 4, 12, 12, 53, 17, 826257, tzinfo=<UTC>), 27)

由多个后台作业同时执行。在这种情况下,计数器会自动更新吗?我正在使用自动提交模式(Django 默认)。

【问题讨论】:

  • Counter 无论如何都会自动更新,无论是显式还是隐式事务(自动提交)。一些信息在这里postgresql.org/docs/current/static/sql-begin.htm
  • 问题更多的是关于查询是否会由多个后台作业同时执行没有竞争条件。 SE 上的文档和其他类似的 questions 并不清楚(他们使用更新单个列的语句)。

标签: python django postgresql concurrency


【解决方案1】:

您可能需要一个 F 表达式:https://docs.djangoproject.com/en/2.1/ref/models/expressions/#f-expressions

来自文档:F() 的另一个有用的好处是让数据库(而不是 Python)更新字段的值可以避免竞争条件。

from django.db.models import F
instance = MyModel.objects.get(pk=xxx)
instance.counter = F('instance.counter') + 1
instance.owner = null
instance.save()

重新加载实例以从 db 获取更新的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    相关资源
    最近更新 更多