forked from rails/deadlock_retry
-
Notifications
You must be signed in to change notification settings - Fork 28
Open
Description
If a deadlock occurs in an after commit hook for a record deadlock_retry will retry the commit but issues an "UPDATE" instead of an "INSERT" statement, resulting in the record never being saved even though calling #save returns true. This is easily demonstrated with the following code:
require 'deadlock_retry'
class MyTest < ActiveRecord::Base
after_create :deadlock_error
after_commit :puts_after_commit, :on => :create
def deadlock_error
unless @errored
@errored = true
raise ActiveRecord::StatementInvalid.new("Deadlock found when trying to get lock")
end
return
end
def puts_after_commit
puts "After Commit"
end
end
my_test = MyTest.new(:name => "Testing")
if my_test.save
MyTest.find(my_test.id)
end
This will have the following output:
> my_test = MyTest.new(:name => "Testing")
=> #<MyTest id: nil, name: "Testing">
> if my_test.save
?> MyTest.find(my_test.id)
?> end
After Commit
ActiveRecord::RecordNotFound: Couldn't find MyTest with ID=1
from /Users/dimas/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.11/lib/active_record/relation/finder_methods.rb:306:in `find_one'
from /Users/dimas/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.11/lib/active_record/relation/finder_methods.rb:291:in `find_with_ids'
from /Users/dimas/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.11/lib/active_record/relation/finder_methods.rb:107:in `find'
from /Users/dimas/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.11/lib/active_record/base.rb:444:in `__send__'
from /Users/dimas/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.11/lib/active_record/base.rb:444:in `find'
from (irb):22
And if you look at the log you'll see:
SQL (0.1ms) BEGIN
SQL (1.9ms) describe `my_tests`
AREL (0.2ms) INSERT INTO `my_tests` (`name`) VALUES ('Testing')
SQL (0.5ms) ROLLBACK
Deadlock detected on retry 1, restarting transaction
SQL (3.3ms) BEGIN
AREL (0.3ms) UPDATE `my_tests` SET `name` = 'Testing' WHERE `my_tests`.`id` = 1
SQL (0.1ms) COMMIT
MyTest Load (0.2ms) SELECT `my_tests`.* FROM `my_tests` WHERE `my_tests`.`id` = 1 LIMIT 1
Metadata
Metadata
Assignees
Labels
No labels