在Rails中使用ActiveJob时,如何避免数据库死锁?

时间:2016-09-28 14:06:09

标签: ruby-on-rails sql-server activerecord database-deadlocks rails-activejob

我过去没有很多遇到死锁问题的经验,但是我越是尝试使用ActiveJob并同时处理这些工作,我就遇到了这个问题。下面显示了创建它的一个Job的示例。它的运作方式是我启动ImportGameParticipationsJob并排队等待CreateOrUpdateGameParticipationJobs

当试图阻止我的SQL Server警告我大量的死锁错误时,下面可能发生的原因在哪里?我可以通过简单地选择记录来填充对象来解决僵局吗?或者它真的只会在我保存时尝试在我的process_records方法中保存/更新记录时才会发生吗?

ImportGameParticipationsJob

class ImportGameParticipationsJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    import_participations(args.first.presence)
  end

  def import_participations(*args)
    games = Game.where(season: 2016)
    games.each do |extract_record|
      CreateOrUpdateGameParticipationJob.perform_later(extract_record.game_key)
    end
  end   
end

CreateOrUpdateGameParticipationJob

class CreateOrUpdateGameParticipationJob < ActiveJob::Base
  queue_as :import_queue

   def perform(*args)
     if args.first.present?
       game_key = args.first

       # get all particpations for a given game
       game_participations = GameRoster.where(game_key: game_key)
       process_records(game_participations)
     end
   end

   def process_records(participations)
     # Loop through participations and build record for saving...
     participations.each do |participation|
       if participation.try(:player_id)
         record = create_or_find(participation)
         record = update_record(record, participation)
       end

       begin
         if record.valid?
           record.save
         else

         end
       rescue Exception => e

       end
     end
   end

   def create_or_find(participation)
     participation_record = GameParticipation.where(
       game_id: participation.game.try(:id),
       player_id: participation.player.try(:id))
       .first_or_initialize do |record|
         record.game = Game.find_by(game_key: participation.game_key)
         record.player   = Player.find_by(id: participation.player_id)
         record.club     = Club.find_by(club_id: participation.club_id)
         record.status   = parse_status(participation.player_status)
     end
     return participation_record
   end

   def update_record(record, record)
     old_status = record.status
     new_status = parse_status(record.player_status)
     if old_status != new_status
       record.new_status = record.player_status
       record.comment    = "status was updated via participations import job"
     end
     return record
   end

end

1 个答案:

答案 0 :(得分:0)

他们最近更新并添加了一个可以设置的附加选项,可以帮助解决死锁问题。我有同样的问题,在4.1上,转到4.1.1为我解决了这个问题。

https://github.com/collectiveidea/delayed_job_active_record

https://rubygems.org/gems/delayed_job_active_record

  

锁定作业时出现问题

     

您可以尝试使用旧版锁定代码。它通常较慢,但对某些人来说效果更好。

     

延迟::后端:: ActiveRecord.configuration.reserve_sql_strategy =:default_sql