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

Rails 6.1中无需原生SQL实现ActiveRecord关系加锁更新的方法

Rails 6.1 锁行更新的官方实现方案

你不需要手写原生SQL就可以实现事务内加行锁再更新的需求,ActiveRecord 本身提供了公开稳定的API支持该操作:

Foo.transaction do
  # 用 ActiveRecord 查询方法构造匹配条件,自动避免SQL注入风险
  foos_query = Foo.where(
    type: 'bar',
    associated_object: thing_id,
    other_party_id: user_id
  ).order(:id)

  # 官方API:直接对匹配行加 FOR UPDATE 锁,无需返回业务数据即可完成加锁
  foos_query.lock!

  # 执行批量更新,此时行已被锁定,不会出现并发更新冲突
  foos_query.update_all(read: "true", seen: true)
end

低开销优化方案

如果你担心默认加锁查询会返回多余字段浪费带宽,可以使用以下轻量写法,只会查询一个常量值,性能和手写原生SELECT FOR UPDATE几乎无差异,且兼容所有支持lock方法的Rails版本:

Foo.transaction do
  foos_query = Foo.where(
    type: 'bar',
    associated_object: thing_id,
    other_party_id: user_id
  ).order(:id)

  # 仅查询常量1完成加锁,不加载任何业务数据和模型对象
  foos_query.lock.pluck(Arel.sql('1'))

  foos_query.update_all(read: "true", seen: true)
end

说明

  • lock、lock! 都是ActiveRecord Relation的官方公开API,Rails 5+ 全版本稳定支持,6.1可以放心使用,不需要依赖非官方的hack实现。
  • 用ActiveRecord原生查询方法构造条件,会自动做参数转义,比手动拼接原生SQL的安全性高很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 08:36:04