【问题标题】:Unusual ActiveRecord Behavior异常的 ActiveRecord 行为
【发布时间】:2016-11-14 23:56:59
【问题描述】:

在高度争用期间,我在下表中查找/创建特定记录时遇到了意外情况。我相信数据库中存在竞争条件。

  create_table "business_objects", force: :cascade do |t| 
    t.string   "obj_id",     limit: 255 
    t.string   "obj_type",   limit: 255 
    t.datetime "created_at",             precision: 6, null: false
  end 

  add_index "business_objects", ["obj_type", "obj_id"], name: "index_business_objects_on_obj_type_and_obj_id", unique: true, using: :btree

违规代码:

def find_or_create_this
 attributes = self.attributes.slice('obj_id', 'obj_type')
 BusinessObject.find_or_create_by!(attributes) 
rescue ActiveRecord::RecordNotUnique
  BusinessObject.find_by!(attributes)
end

find_or_create_by! 中的查找返回 nil 并触发 create! 引发 ActiveRecord::RecordNotUnique 错误。救援块捕获它并尝试查找导致非唯一错误的记录,但它也返回 nil。我的期望是,如果违反索引唯一性约束,则应将记录提交到表中。我错过了什么?

【问题讨论】:

    标签: mysql ruby ruby-on-rails-3 activerecord


    【解决方案1】:

    要回答我自己的问题,请研究 MySQL 的事务隔离级别。将违规代码包装在事务块中并修改隔离级别。

    选项有:

    1. 阅读未提交
    2. 可序列化
    3. 可重复读取
    4. 已提交阅读

      def find_or_create_this attributes = self.attributes.slice('obj_id', 'obj_type') ActiveRecord::Base.transaction(isolation: :read_committed) do BusinessObject.find_or_create_by!(attributes) end rescue ActiveRecord::RecordNotUnique ActiveRecord::Base.transaction(isolation: :read_committed) do BusinessObject.find_by!(attributes) end end

    【讨论】:

      猜你喜欢
      • 2014-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-15
      相关资源
      最近更新 更多