【问题标题】:Data integrity when updating/incrementing values in Rails在 Rails 中更新/增加值时的数据完整性
【发布时间】:2010-03-04 05:48:57
【问题描述】:

我正在开发一个应用程序,其中一个模块访问日志(ActiveRecord 模型)以在执行的几个点增加各种值。问题是该脚本可能需要几秒钟,并且同一脚本的其他实例可能同时运行。

我看到的是,虽然脚本正确完成并考虑了所有数据,但值永远不会正确。这可能是因为当脚本到达它更新值的点时,列的读取值(递增)已经过时了。

如果我强制它一次只有一个模块实例,则这些值是正确的,但出于性能原因,我不能继续这样做。

目前,我尝试通过在事务中的每个增量语句之前查询数据库中的记录来解决该问题,如下所示,其中column 是列的符号,value 是 1 或更高:

Log.transaction do
  log = Log.find(@log_id)
  log.update_attribute(column, log.send(column) + value)
end

但是,它仍然不会给我准确的数字。我认为涉及到缓存,我想我可以尝试以下方法:

Log.transaction do
  uncached do
    log = Log.find(@log_id)
    log.update_attribute(column, log.send(column) + value)
  end
end

但我肯定不会是第一个遇到这个问题的人,所以我想知道是否有更好的实现/解决方案来解决我的问题?

【问题讨论】:

    标签: ruby-on-rails ruby database activerecord


    【解决方案1】:

    ActiveRecord 提供了一个update_counters 方法。您可以按如下方式更改代码:

    Log.update_counters @log_id, column.to_sym => value
    

    【讨论】:

    • 这看起来是个不错的选择。不敢相信我错过了那个。将测试并看看它是如何工作的。
    • 如果两个脚本在重叠事务中调用update_counters,你仍然有竞争条件;一个会覆盖另一个的update。如果您想要真正的顺序性,您必须锁定行 (Model.find(..., :lock => true))、表或使用外部例如文件系统或 IPC 锁。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 2023-04-04
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多