ActiveRecord :: StatementInvalid:Mysql2 :: Error:超出锁定等待超时

时间:2016-05-17 08:06:31

标签: mysql ruby-on-rails activerecord sidekiq

在我的rails项目中,我使用sidekiq处理耗时的任务,但在sidekiq日志中出现错误:

ActiveRecord::StatementInvalid: Mysql2::Error: Lock wait timeout exceeded; try restarting transaction: UPDATE `marker_layers` SET `show_fields` = 'title,desc', `sort_col` = 'title,desc', `updated_at` = '2016-05-17 07:36:02' WHERE `marker_layers`.`id` = 16021210
Processor: iZ23edse84Z:29310

enter image description here sidekiq.yml

# Options here can still be overridden by cmd line args.
#   setsid sidekiq -d -C config/sidekiq.yml -e production
---
:concurrency: 5
:pidfile: tmp/pids/sidekiq.pid
:logfile: log/sidekiq.log
staging:
  :concurrency: 10
production:
  :concurrency: 40
:queues:
  - ['critical', 3]
  - ['default', 2]
  - ['low', 1]

的database.yml

production:
   adapter: mysql2
   encoding: utf8mb4
   collation: utf8mb4_bin
   reconnect: false
   database: database_name
   pool: 48
   username: password
   password: password
   host: locahost

3 个答案:

答案 0 :(得分:0)

发生此错误是因为当不同的工作程序尝试修改相同的资源时,事务超时,基本上是数据库死锁。

如果您正在使用明确的SomeModel.transaction { SomeModel.task_that_takes_too_much_time }之类的事务,或者使用修改记录的普通ActiveRecord方法,则会发生这种情况,因为所有内容都包含在事务中。

我能给你的唯一建议是探索让你的员工独特的替代方案,例如使用https://github.com/mhenrixon/sidekiq-unique-jobs并让你的工作使用.perform_in

答案 1 :(得分:0)

当数据库大小增加并且你明确地做了很多事务时会发生这种情况,可能是其他一些线程在某些记录上持有记录锁定的时间太长,并且你的线程正在超时。

我使用的一种解决方案是延长等待超时。

通过终端登录MySQL并运行它。

SET GLOBAL innodb_lock_wait_timeout = 28800;

你可以做的另一件事是 FORCE UNLOCK for MySQL中的锁定表:

像这样打破锁定通常会导致数据库中的原子性不会在导致锁定的sql语句上强制执行。

这是一个黑客。正确的解决方案是修复导致锁定的应用程序。

FORCE UNLOCK for locked tables in MySQL:

答案 2 :(得分:0)

这意味着操作记录已经被另一个缓慢的SQL锁定,并且等待了很长时间。

可能是您代码中的许多长事务。

检查代码,优化慢速SQL并拆分长事务。

我希望这对你有所帮助。