2016-05-17 90 views
4

在我的轨道项目中,我使用sidekiq处理耗时的任务,但在sidekiq记录一个错误:的ActiveRecord :: StatementInvalid:Mysql2 ::错误:锁等待超时超标

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 
+2

很可能多个工作人员尝试更新相同的数据库行,并在等待访问时出现一些超时。根据你的信息,我们不能说更多。您应该重新检查您的代码是否存在竞争条件并查看死锁的来源... – averell

+1

您可能会发现http://stackoverflow.com/questions/6000336/how-to-debug-lock-wait-timeout-exceeded有帮助 –

回答

0

当不同的工作人员尝试修改相同的资源时(基本上是数据库死锁),由于事务超时而发生此错误。

它发生或者如果您使用的交易明确地像SomeModel.transaction { SomeModel.task_that_takes_too_much_time }或使用正常的ActiveRecord的方法是修改记录,因为一切都被包裹成一个事务。

唯一的建议我可以给你的是探索的替代品使用https://github.com/mhenrixon/sidekiq-unique-jobs,使您的工作使用.perform_in让你的员工独特,等等。

+0

我会同时处理很多任务, – scottxu

0

这发生在数据库大小和成长,你明确地做了很多交易,可能是一些其他线程持有记录锁定的一些记录得太久,你的线程被超时。我用

一个解决方案,就是延长等待超时。

登录到MySQL通过终端并运行此。

SET GLOBAL innodb_lock_wait_timeout = 28800; 

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

这样的破锁常常会导致原子在数据库中不导致锁定的SQL语句执行。

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

FORCE UNLOCK for locked tables in MySQL:

0

这意味着在工作记录已被其他慢SQL锁定,并且已经等待了很久。

也许这就是在你的代码中的许多长事务。

检查你的代码,优化SQL速度慢,分裂长事务。

我希望这可以对你有所帮助。

+0

是的,但我不知道如何解决它。 – scottxu