过去我并没有很多死锁问题的经验,但我越来越多地尝试使用ActiveJob并同时处理这些作业,所以我遇到了这个问题。下面显示了创建它的一个Job的示例。它的运作方式是我开始ImportGameParticipationsJob
,它排队了一堆CreateOrUpdateGameParticipationJobs
。在Rails中使用ActiveJob时,如何避免数据库发生死锁?
当试图阻止我的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
我没有使用'DelayedJob',使用'Sidekiq' – daveomcd
啊,我们正在转换现在就Sidekiq上一堆应用程序,所以我希望我不会遇到同样的事情。 –