ActiveRecord::StatementInvalid:Mysql2::错误:超过锁定等待超时

ActiveRecord::StatementInvalid:Mysql2::错误:超过锁定等待超时,mysql,ruby-on-rails,activerecord,sidekiq,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` =

在我的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
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]
production:
   adapter: mysql2
   encoding: utf8mb4
   collation: utf8mb4_bin
   reconnect: false
   database: database_name
   pool: 48
   username: password
   password: password
   host: locahost
数据库.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]
production:
   adapter: mysql2
   encoding: utf8mb4
   collation: utf8mb4_bin
   reconnect: false
   database: database_name
   pool: 48
   username: password
   password: password
   host: locahost

发生此错误的原因是,当不同的工作人员试图修改同一资源时,事务超时,基本上是数据库死锁

如果您显式地使用事务,如花费太多时间的
SomeModel.transaction{SomeModel.task}
,或者使用普通的ActiveRecord方法修改记录,因为所有内容都打包到事务中,则会发生这种情况


我能给你的唯一建议是探索其他方法,使你的工作人员独一无二,比如使用并使你的工作使用
。在

中执行\u这发生在数据库大小增加时,并且你显式地做了很多事务,可能其他线程在某个记录上持有记录锁的时间过长,您的线程正在超时

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

通过终端登录MySQL并运行此命令

SET GLOBAL innodb_lock_wait_timeout = 28800;
您可以做的另一件事是强制解锁MySQL中锁定的表:

像这样破坏锁通常会导致数据库中的原子性无法在导致锁的sql语句上强制执行

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


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

也许代码中有很多长事务

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


我希望这能对您有所帮助。

很可能有多个工作人员尝试更新同一数据库行,并且在等待访问时超时。根据你的信息,我们不能说更多了。您可能应该重新检查您的代码是否存在争用条件,并查看死锁来自何处……您可能会发现有帮助您可能还想了解
innodb\u lock\u wait\u timeout
innodb\u deadlock\u detect
变量