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

Rails/ActiveRecord:如何利用锁避免多线程同时更新模型

解决Rails中Model实例并发更新的问题

嘿,你提到的这个并发更新场景在Rails开发里真的很典型——尤其是webhook这类异步请求和常规业务操作撞在一起的时候,很容易出现数据冲突。

首先得给你确认:model_name_instance.with_lock确实是Rails官方推荐的解决方案,它的工作逻辑很清晰:

  • 自动启动一个新事务
  • 对目标数据库行加排他锁(exclusive lock)
  • 其他线程想要对该行执行UPDATE/DELETE操作时,必须等待当前锁释放才能继续

这就完美解决了你担心的“两个线程同时修改同一条Model记录”的问题,能有效避免更新丢失或者数据不一致的情况。

不过你观察得很准:这个方法确实不会阻止其他线程读取该行数据。这是因为大多数数据库(比如PostgreSQL、MySQL)的默认事务隔离级别下,读操作不会被排他锁阻塞——其他线程仍然能读到该行的最新提交版本(或者当前未提交的版本,取决于隔离级别)。如果你的业务场景里,读取中间状态会导致逻辑错误,那你可能需要额外处理:

  • 可以手动调整事务的隔离级别(比如用Serializable级别),但这会增加死锁风险,需要谨慎评估
  • 或者在读取操作时也加共享锁,比如用ModelName.lock.find(model_id)来确保读取的是锁定后的一致状态

给你一个实际业务中常用的代码示例,比如处理webhook更新时的写法:

def process_webhook_update(model_id, payload)
  model = ModelName.find(model_id)
  model.with_lock do
    # 所有涉及修改model的操作都放在lock块内
    model.update!(
      status: :completed,
      transaction_amount: model.transaction_amount + payload[:add_amount]
    )
    # 比如关联的日志记录也可以放在这里,保证原子性
    model.transaction_logs.create!(detail: "Webhook added #{payload[:add_amount]}")
  end
end

最后提个小建议:with_lock块里的逻辑尽量精简,锁持有时间越长,越容易让其他请求进入等待状态,影响系统性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:03:03