Rails - 乐观锁定总是触发 StaleObjectError 异常

Posted

技术标签:

【中文标题】Rails - 乐观锁定总是触发 StaleObjectError 异常【英文标题】:Rails - Optimistic locking always fires StaleObjectError exception 【发布时间】:2015-04-28 01:05:39 【问题描述】:

我正在学习 rails,并阅读有关乐观锁的信息。我已将integer 类型的lock_version 列添加到我的articles 表中。

但是现在每当我尝试第一次更新记录时,我都会收到StaleObjectError 异常。

这是我的迁移:

class AddLockVersionToArticle < ActiveRecord::Migration
  def change
    add_column :articles, :lock_version, :integer
  end
end

当我尝试通过 rails 控制台更新文章时:

article = Article.first
=> #<Article id: 1, title: "Ccccc", text: "dfdsfsdfsdf", created_at: "2015-02-20 21:58:45", updated_at: "2015-02-25 20:03:12", lock_version: 0>

我愿意:

article.title = "new title"
article.save

我明白了:

(0.3ms)  begin transaction
   (0.3ms)  UPDATE "articles" SET "title" = 'dwdwd', "updated_at" = '2015-02-25 20:40:36.537876', "lock_version" = 1 WHERE ("articles"."id" = 1 AND "articles"."lock_version" = 0)
   (0.1ms)  rollback transaction
ActiveRecord::StaleObjectError: Attempted to update a stale object: Article

【问题讨论】:

可能是默认值,但是锁版本列应该有默认值0(在数据库中) 你确定你是第一次这样做吗? @FrederickCheung lock_version 已经是 0 【参考方案1】:

您必须将所有文章 lock_version 初始化为 0。 看查询:

UPDATE "articles" SET "title" = 'dwdwd', "updated_at" = '2015-02-25 20:40:36.537876', "lock_version" = 1 WHERE ("articles"."id" = 1 AND "articles"."lock_version" = 0)
       (0.1ms) 

如果查询返回 0 条更新记录,则框架假设您已更新版本或删除了另一个线程中的对象。

【讨论】:

所以迁移应该是:add_column :articles, :lock_version, :integer, default: 0, null: false 我投了反对票,lock_version 已经是 0,并且在示例中,作者使用 bin/rails 控制台 @CodeGroover 显然 rails 控制台显示 lock_verison 的值为 0。但是当我检查数据库时,它有null 值。将列更改为具有默认值可以解决问题。

以上是关于Rails - 乐观锁定总是触发 StaleObjectError 异常的主要内容,如果未能解决你的问题,请参考以下文章

为啥activerecord乐观锁定每行只工作一次?

CoreData:错误:无法解决乐观锁定失败:乐观锁定失败(null),只有旧记录,为啥?

Spring data - 启用乐观锁定

乐观与悲观锁定

何时明确排除乐观锁定(休眠)?

休眠乐观锁定..它是如何工作的?