【问题标题】:MySQL foreign key constraints throws ActiveRecord::StatementInvalid (Lock wait timeout) in my Rails 3.1 applicationMySQL 外键约束在我的 Rails 3.1 应用程序中抛出 ActiveRecord::StatementInvalid (Lock wait timeout)
【发布时间】:2012-02-25 23:56:22
【问题描述】:
**Software Versions:**

Rails 3.1.3
MySQL 5.5.21
OS: MacOS 10.7.3

今天我在我的 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 还是 MyISAM?当应用程序崩溃时,您可以发布您的日志示例吗?当然,如果还不算太晚:)
  • @basgys 这是什么问题? MyISAM 不支持外键检查。因此我很确定它是 InnoDB。

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


【解决方案1】:

这是一个死锁。

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

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

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

【讨论】:

  • 在数据库级别以及和在应用程序级别强制引用完整性几乎总是一个好主意。程序员会犯错误,并且由于数据库强制执行外键而在运行时获得异常总比因上述错误而丢失有价值的生产数据要好。
  • 你错了。你的建议在理论上是好的,但在实践中并不好。在大型系统中,您希望数据库做的工作尽可能少,否则您将永远无法实现规模化。这个困境的解决方案是除了应用程序级别的完整性检查之外,还进行定期的数据库完整性检查。这也使您的应用程序免于与特定数据库实现过于紧密地耦合并实现模块化。
猜你喜欢
  • 2016-09-13
  • 2011-06-14
  • 2015-10-29
  • 1970-01-01
  • 2018-08-30
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多