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

Django中GET请求引发的竞态问题及修复方法咨询

问题修复方案

核心原因

你遇到的是竞态条件:

  1. 前端循环同步发起两个XHR请求,浏览器会并行处理,两个请求几乎同时到达后端
  2. Django默认每个请求对应独立事务,第一个请求的save()操作还未提交到数据库时,第二个请求已经执行了Appointment.objects.all()查询,导致两次都读到旧数据

修复方案(前端+后端结合,确保彻底解决)

1. 前端:改为串行发起请求

确保第一个请求完成后再发起第二个,避免并行请求:

// 封装XHR为Promise
function createAppointment() {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', "make_appointment/");
    xhr.onload = () => resolve(xhr.response);
    xhr.onerror = reject;
    xhr.send();
  });
}

// 串行执行两次请求
async function createTwoAppointments() {
  for (let i = 0; i < 2; i++) {
    await createAppointment();
  }
}

// 调用执行
createTwoAppointments();

2. 后端:添加并发控制(关键,防止其他场景的竞态)

即使前端串行,若有其他客户端同时调用该接口,仍可能出现问题,需在后端加事务锁:

from django.db import transaction
from django.contrib.auth.decorators import login_required

@login_required
def make_appointment(request):
    # 开启原子事务,确保查询和保存操作是原子性的
    with transaction.atomic():
        # 使用select_for_update锁定所有Appointment记录,直到事务结束
        # 这样其他请求必须等待当前事务完成才能查询
        existing_count = Appointment.objects.select_for_update().count()
        print('existing_appointments = ', existing_count)
        
        new_appointment = Appointment()
        new_appointment.save()
    # 返回响应(比如重定向或JSON)
    return redirect('/some-page/')

简化替代方案(若仅需计数)

如果只是需要获取当前预约数量,无需查询所有记录,可直接用原子计数:

@login_required
def make_appointment(request):
    existing_count = Appointment.objects.count()
    print('existing_appointments = ', existing_count)
    new_appointment = Appointment()
    new_appointment.save()
    # ...

注:count()是原子操作,但如果你的业务逻辑依赖count()结果进行后续操作(比如设置预约序号),仍需用select_for_update确保原子性。


验证效果

修复后日志会符合预期:

[18/Dec/2024 17:42:48] "GET /make_appointment/ HTTP/1.1" 302 0
existing_appointments =  0
[18/Dec/2024 17:42:48] "GET /make_appointment/ HTTP/1.1" 302 0
existing_appointments =  1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:10:16