MySQL 外键约束在我的 Rails 3.1 应用程序中抛出 ActiveRecord::StatementInvalid(锁定等待超时)

标签 mysql ruby-on-rails activerecord ruby-on-rails-3.1

**Software Versions:**

Rails 3.1.3
MySQL 5.5.21
OS: MacOS 10.7.3

今天我用 foreigner gem 向我的 MySQL 数据库添加了很多外键约束。 但是现在我在简单插入时得到“锁定等待超时”异常:

ActiveRecord::StatementInvalid (Mysql2::Error: Lock wait timeout exceeded; 
try restarting   transaction

如果我从我的数据库中删除外键约束,问题就消失了。

当我尝试添加一个包含“has_one”与“accepts_nested_attributes_for”关联数据的对象时,问题发生了:

class MyApp::PrimaryData < ActiveRecord::Base
    has_one :sub_data, :dependent => :destroy
    accepts_nested_attributes_for :sub_data
    [...]
end

class MyApp::SubData < ActiveRecord::Base
    belongs_to :primary_data
    attr_accessible :field1, :field2
    [...]
end

table: primary_data
-------------------
- id (integer)
- field1 (string)
  [...]


table: sub_data
---------------
- id (integer)
- primary_data_id (integer)
- field1 (string)
- field2 (string)
  [...]

-> foreign_key_contraint on primary_data_id --> table primary_datas (id)

如果我只是创建没有“SubData”的“PrimaryData”,或者分别创建“PrimaryData”和“SubData”,那么我不会收到任何 MySQL 错误,只有当我尝试使用一些“SubData”创建“PrimaryData”时” 以 Rails 的“accepts_nested_attributes_for”方式。

谁能帮我解决这个问题? 提前致谢。

最佳答案

这是一个死锁。

当您在具有外键约束的表中添加一行时,MySQL 将同时获取此表(或 InnoDB 中的行)和引用表(或 InnoDB 中的行)的锁。

在这种特殊情况下,当您使用 SubData 创建 PrimaryData 时,MySQL 首先获取 primary_data 的锁,然后获取 sub_data 的锁,然后在获取 primary_data 的另一个锁时死锁。

一般来说,在 Rails 中使用外键并不是一个好主意。将事件记录验证器用于这些目的。

关于MySQL 外键约束在我的 Rails 3.1 应用程序中抛出 ActiveRecord::StatementInvalid(锁定等待超时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9449256/

相关文章:

mysql - 通过将两个整数变量与 MySQL 连接来生成新的字符串变量

ruby-on-rails - 从 Rails 应用程序访问 Salesforce 和查询

ruby-on-rails - Rails - 从参数更新对象

html - 访问 Rails 后端的 Javascript 变量

ruby-on-rails - Rails 3.1 路由错误

ruby-on-rails - 我如何find()在某些字段中唯一的所有记录?

activerecord - Yii2 Active Record 类 load() 或 save() 不更新数据

mysql - GROUP BY 并排序

MYSQL sql在表中查找计数大于x的id

PHP/MySQL - 外键问题