Skip to content
Browse files

add a pause before retrying deadlocked transactions

  • Loading branch information...
1 parent 9988cd5 commit 0ecde254808753cf86d248f2e3f6ea290fc101ae @jamis committed Dec 12, 2011
Showing with 17 additions and 2 deletions.
  1. +17 −2 lib/deadlock_retry.rb
View
19 lib/deadlock_retry.rb
@@ -28,6 +28,13 @@ module DeadlockRetry
mattr_accessor :deadlock_logger
self.deadlock_logger = proc { |msg, klass| klass.logger.warn(msg) if klass.logger }
+ # Define how long to wait before retrying a transaction, in milliseconds.
+ mattr_accessor :minimum_wait_before_retry
+ mattr_accessor :maximum_wait_before_retry
+
+ self.minimum_wait_before_retry = 100
+ self.maximum_wait_before_retry = 500
+
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
@@ -52,14 +59,22 @@ def transaction_with_deadlock_handling(*objects, &block)
raise if in_nested_transaction?
raise unless DEADLOCK_ERROR_MESSAGES.any? { |msg| error.message =~ /#{Regexp.escape(msg)}/i }
- DeadlockRetry.deadlock_logger.call("Deadlock detected on retry #{retry_count}, restarting transaction", self)
-
if retry_count >= DeadlockRetry.maximum_retries_on_deadlock
+ DeadlockRetry.deadlock_logger.call("Deadlock detected after #{retry_count+1} tries, giving up", self)
log_innodb_status
raise
end
retry_count += 1
+
+ pause = DeadlockRetry.minimum_wait_before_retry +
+ rand(DeadlockRetry.maximum_retries_on_deadlock -
+ DeadlockRetry.minimum_wait_before_retry)
+
+ DeadlockRetry.deadlock_logger.call("Deadlock detected on try ##{retry_count}, restarting transaction in #{pause}s", self)
+
+ sleep(pause / 1000.0)
+
retry
end
end

0 comments on commit 0ecde25

Please sign in to comment.
Something went wrong with that request. Please try again.