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

如何锁定ChecklistItem关联对象以避免竞态条件?

解决ChecklistItem并发更新引发的竞态条件问题

问题拆解

你判断的没错,这就是竞态条件导致的问题:当多个ChecklistItem被快速保存时,每个实例的update_checklist_completion方法会各自查询数据库。最后一个执行的方法可能读取到还未被其他请求更新的旧数据,误判仍有未完成项,导致Checklist没能被标记为已完成。

实用解决方案

1. 用数据库行锁(悲观锁)彻底解决并发冲突

直接锁定对应的Checklist记录,确保同一时间只有一个请求能修改它的状态。修改update_checklist_completion方法:

def update_checklist_completion
  # 启动事务并锁定Checklist行,事务结束后才释放锁
  checklist.with_lock do
    # 重新从数据库加载最新数据,避免依赖内存中的旧对象
    checklist.reload
    # 基于最新数据更新完成状态
    checklist.update(completed: checklist.checklist_items.unchecked.none?)
  end
end

with_lock是Rails提供的便捷方法,会自动开启事务并给Checklist行加排他锁,其他请求必须等待当前事务完成才能操作这条记录,从根源上杜绝并发冲突。

2. 直接用数据库查询统计状态,不依赖内存对象

不要依赖siblings这类内存中的关联集合,直接通过数据库查询未完成项的数量,确保每次读取的都是最新数据:

def update_checklist_completion
  # 直接查询数据库中未完成的项数
  unchecked_count = ChecklistItem.where(checklist_id: checklist.id, checked: false).count
  checklist.update(completed: unchecked_count.zero?)
end

这种方法简单高效,普通场景下够用。如果是超高并发场景,可以套一层事务强化:

def update_checklist_completion
  Checklist.transaction do
    unchecked_count = ChecklistItem.where(checklist_id: checklist.id, checked: false).count
    checklist.update(completed: unchecked_count.zero?)
  end
end

3. 把after_save替换为after_commit

after_save在事务提交前执行,此时当前请求的修改还未写入数据库,其他并发请求的修改也可能未落地。换成after_commit能确保当前修改持久化后,再去检查并更新状态:

# 指定仅在创建或更新操作提交后触发
after_commit :update_checklist_completion, on: [:create, :update]

def update_checklist_completion
  unchecked_count = ChecklistItem.where(checklist_id: checklist.id, checked: false).count
  checklist.update(completed: unchecked_count.zero?)
end

这个方法能减少大部分并发问题,但极端高并发场景下,建议配合数据库锁使用。

4. 批量操作时统一更新状态(从源头减少触发次数)

如果是批量完成多个ChecklistItem的场景,不要让每个Item都触发一次状态更新,直接在批量操作后统一更新Checklist:

# 批量更新示例
ChecklistItem.where(id: item_ids).update_all(checked: true)
# 统一更新对应Checklist的完成状态
checklist = Checklist.find(checklist_id)
checklist.update(completed: checklist.checklist_items.unchecked.none?)

这种方式减少了并发触发状态更新的次数,自然降低了竞态条件出现的概率。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:25:09