【问题标题】:ActiveRecord "Mysql::Error: Lock wait timeout exceeded" with no apparent locksActiveRecord "Mysql::Error: Lock wait timeout exceeded" 没有明显的锁
【发布时间】:2011-06-14 19:22:32
【问题描述】:

Rails 版本:2.3.8

一天中的很多时候,我的应用程序似乎会随机返回一个 500 错误,并在生产日志中显示相应条目:

ActiveRecord::StatementInvalid (Mysql::Error: Lock wait timeout exceeded; try restarting transaction: INSERT INTO `forum_posts` (`forum_topic_id`, `created_at`, `body`, `ancestry`, `updated_at`, `quote_limit`, `user_id`, `ancestry_depth`, `quote_root`) VALUES(1224783, '2011-01-24 19:18:38', 'Post body', '1285704', '2011-01-24 19:18:38', 1, 57931, 1, 1))

检查 MySQL 慢查询日志显示此条目为:

# Time: 110124 11:19:29
# User@Host: db_user[db_user] @ localhost []
# Query_time: 51  Lock_time: 0  Rows_sent: 0  Rows_examined: 0
SET insert_id=0;
INSERT INTO `forum_posts` (`forum_topic_id`, `created_at`, `body`, `ancestry`, `updated_at`, `quote_limit`, `user_id`, `ancestry_depth`, `quote_root`) VALUES(1224783, '2011-01-24 19:18:38', 'Post body', '1285704', '2011-01-24 19:18:38', 1, 57931, 1, 1);

根据 Rails 日志,ActiveRecord 由于锁定等待超时而返回错误。这个简单查询的长期运行性质似乎也表明了这一点。问题是,慢查询日志无处可寻,我可以找到一个需要很长时间来处理的实际查询——它们都与上面的示例相似。另外,在同一个日志中,没有一个条目的 Lock_time 值大于 0。

这里有没有人知道什么可能导致这种明显的锁定以及如何隔离它?我正在使用的当前工具似乎没有多大帮助。

提前致谢。

【问题讨论】:

  • 通过show innodb status 显示的任何长期交易?这些可能会创建隐式锁,而这些锁不会出现在其他地方。
  • 目前没有。 Total number of lock structs in row lock hash table 也是 0。
  • 我正在追查同样的问题。我不认为你解决了它?
  • 和我一样。有什么解决办法吗?

标签: mysql ruby-on-rails activerecord locking timeout


【解决方案1】:

也许这会有所帮助: http://www.mysqlperformanceblog.com/2007/02/25/pitfalls-of-converting-to-innodb/

我们经常建议我们的客户将他们当前的数据库从 MyISAM 表转换为 InnoDB。 在大多数情况下,传输本身几乎是简单的,但是应用程序可能会因新的意外错误而中断 1205 (ER_LOCK_WAIT_TIMEOUT) 锁定等待超时已过期。事务已回滚。 第1213章 事务死锁。您应该重新运行事务。

处理这些错误并不难,但您应该注意。 这是我们在 PHP 应用程序中所做的一些事情:

class mysqlx extends mysqli {

...

  function deadlock_query($query) {
          $MAX_ATTEMPS = 100;
          $current = 0;
          while ($current++ < $MAX_ATTEMPS) {

                  $res = $this->query($query);

                  if(!$res && ( $this->errno== '1205' || $this->errno == '1213'  ) )
                                  continue;
                  else 
                          break;
             }
 } 
...
}

您可能希望以不同的方式处理 ER_LOCK_WAIT_TIMEOUT,特别是对于长时间等待不好的 Web 应用程序,您明白了。

【讨论】:

    猜你喜欢
    • 2016-09-13
    • 2018-08-30
    • 2015-10-29
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多