在我的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
# 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
答案 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语句上强制执行。
这是一个黑客。正确的解决方案是修复导致锁定的应用程序。
答案 2 :(得分:0)
这意味着操作记录已经被另一个缓慢的SQL锁定,并且等待了很长时间。
可能是您代码中的许多长事务。
检查代码,优化慢速SQL并拆分长事务。
我希望这对你有所帮助。