You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 2.2并发场景下select_for_update能否避免超量创建账户?

Django 2.2并发场景下控制Account创建上限的方案验证

结论

在@transaction.atomic装饰的方法中使用select_for_update()配合count查询,能够解决并发导致的账户超量创建问题,但需要确保完整逻辑都在事务内执行。

原问题根源

原来的代码缺乏并发控制:多个请求同时执行时,会同时读取到相同的unused_count,都判定有剩余名额,进而各自创建账户,最终导致总数量超出上限。

为什么select_for_update()能解决?

select_for_update()会对查询匹配到的所有行添加排他锁,在当前事务提交前,其他并发事务执行相同的查询会被阻塞。这就保证了同一时间只有一个事务能获取准确的剩余名额,避免了"读-改-写"过程中的并发冲突。

注意事项

  1. 完整逻辑必须包裹在原子事务内
    不能只把count查询单独放在事务里,要把"查询剩余名额-创建账户"的整个流程都放在@transaction.atomic装饰的方法中,示例代码:

    from django.db import transaction
    
    @transaction.atomic
    def create_accounts():
        # 加锁查询未使用账户数量
        unused_count = Account.objects.select_for_update().filter(field1__isnull=True, field2__isnull=True).count()
        vacancies = UPPER_LIMIT - unused_count
        if vacancies > 0:
            # 批量创建账户
            Account.objects.bulk_create([Account() for _ in range(vacancies)])
    
  2. 性能优化建议
    如果UPPER_LIMIT数值很大,符合条件的未使用账户数量较多,select_for_update()会锁定大量行,可能影响系统性能。这种情况下可以改用独立计数器表来控制总量,锁的粒度更小:

    # 先定义计数器模型
    class AccountCounter(models.Model):
        total_created = models.IntegerField(default=0)
    
    # 创建逻辑
    @transaction.atomic
    def create_accounts():
        # 锁定计数器行
        counter = AccountCounter.objects.select_for_update().first()
        if not counter:
            counter = AccountCounter(total_created=0)
        vacancies = UPPER_LIMIT - counter.total_created
        if vacancies > 0:
            Account.objects.bulk_create([Account() for _ in range(vacancies)])
            counter.total_created += vacancies
            counter.save()
    

内容的提问来源于stack exchange,提问作者akash deep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:26:08