deadlock_retry 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -1
- data/deadlock_retry.gemspec +1 -1
- data/lib/deadlock_retry.rb +33 -4
- data/test/deadlock_retry_test.rb +20 -2
- metadata +3 -5
data/CHANGELOG
CHANGED
data/deadlock_retry.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{deadlock_retry}
|
5
|
-
s.version = "1.1.
|
5
|
+
s.version = "1.1.1"
|
6
6
|
s.authors = ["Jamis Buck", "Mike Perham"]
|
7
7
|
s.description = s.summary = %q{Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL}
|
8
8
|
s.email = %q{mperham@gmail.com}
|
data/lib/deadlock_retry.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module DeadlockRetry
|
2
|
-
|
3
2
|
def self.included(base)
|
4
3
|
base.extend(ClassMethods)
|
5
4
|
base.class_eval do
|
@@ -9,6 +8,16 @@ module DeadlockRetry
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
11
|
+
@@innodb_status_available = nil
|
12
|
+
|
13
|
+
def self.innodb_status_available?
|
14
|
+
@@innodb_status_available
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.innodb_status_available=(bool)
|
18
|
+
@@innodb_status_available = bool
|
19
|
+
end
|
20
|
+
|
12
21
|
module ClassMethods
|
13
22
|
DEADLOCK_ERROR_MESSAGES = [
|
14
23
|
"Deadlock found when trying to get lock",
|
@@ -17,9 +26,12 @@ module DeadlockRetry
|
|
17
26
|
|
18
27
|
MAXIMUM_RETRIES_ON_DEADLOCK = 3
|
19
28
|
|
29
|
+
|
20
30
|
def transaction_with_deadlock_handling(*objects, &block)
|
21
31
|
retry_count = 0
|
22
32
|
|
33
|
+
check_innodb_status_available
|
34
|
+
|
23
35
|
begin
|
24
36
|
transaction_without_deadlock_handling(*objects, &block)
|
25
37
|
rescue ActiveRecord::StatementInvalid => error
|
@@ -28,7 +40,7 @@ module DeadlockRetry
|
|
28
40
|
raise if retry_count >= MAXIMUM_RETRIES_ON_DEADLOCK
|
29
41
|
retry_count += 1
|
30
42
|
logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
|
31
|
-
log_innodb_status
|
43
|
+
log_innodb_status if DeadlockRetry.innodb_status_available?
|
32
44
|
retry
|
33
45
|
else
|
34
46
|
raise
|
@@ -43,10 +55,27 @@ module DeadlockRetry
|
|
43
55
|
connection.open_transactions != 0
|
44
56
|
end
|
45
57
|
|
58
|
+
def show_innodb_status
|
59
|
+
self.connection.select_value("show innodb status")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Should we try to log innodb status -- if we don't have permission to,
|
63
|
+
# we actually break in-flight transactions, silently (!)
|
64
|
+
def check_innodb_status_available
|
65
|
+
return unless DeadlockRetry.innodb_status_available? == nil
|
66
|
+
|
67
|
+
begin
|
68
|
+
show_innodb_status
|
69
|
+
DeadlockRetry.innodb_status_available = true
|
70
|
+
rescue
|
71
|
+
DeadlockRetry.innodb_status_available = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
46
75
|
def log_innodb_status
|
47
76
|
# show innodb status is the only way to get visiblity into why
|
48
77
|
# the transaction deadlocked. log it.
|
49
|
-
lines =
|
78
|
+
lines = show_innodb_status
|
50
79
|
logger.warn "INNODB Status follows:"
|
51
80
|
lines.each_line do |line|
|
52
81
|
logger.warn line
|
@@ -59,4 +88,4 @@ module DeadlockRetry
|
|
59
88
|
end
|
60
89
|
end
|
61
90
|
|
62
|
-
ActiveRecord::Base.send(:include, DeadlockRetry)
|
91
|
+
ActiveRecord::Base.send(:include, DeadlockRetry)
|
data/test/deadlock_retry_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
# Change the version if you want to test a different version of ActiveRecord
|
4
|
-
gem 'activerecord', '3.0
|
4
|
+
gem 'activerecord', ' ~>3.0'
|
5
5
|
require 'active_record'
|
6
6
|
require 'active_record/version'
|
7
7
|
puts "Testing ActiveRecord #{ActiveRecord::VERSION::STRING}"
|
@@ -32,6 +32,14 @@ class MockModel
|
|
32
32
|
@logger ||= Logger.new(nil)
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.show_innodb_status
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.reset_innodb_status_availability
|
40
|
+
DeadlockRetry.innodb_status_availability = nil
|
41
|
+
end
|
42
|
+
|
35
43
|
include DeadlockRetry
|
36
44
|
end
|
37
45
|
|
@@ -39,6 +47,9 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
39
47
|
DEADLOCK_ERROR = "MySQL::Error: Deadlock found when trying to get lock"
|
40
48
|
TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
|
41
49
|
|
50
|
+
def setup
|
51
|
+
end
|
52
|
+
|
42
53
|
def test_no_errors
|
43
54
|
assert_equal :success, MockModel.transaction { :success }
|
44
55
|
end
|
@@ -71,6 +82,13 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
71
82
|
assert ActiveRecord::Base.respond_to?(:transaction_with_deadlock_handling)
|
72
83
|
end
|
73
84
|
|
85
|
+
def test_innodb_status_availability
|
86
|
+
DeadlockRetry.innodb_status_available = nil
|
87
|
+
MockModel.transaction {}
|
88
|
+
assert_equal true, DeadlockRetry.innodb_status_available?
|
89
|
+
end
|
90
|
+
|
91
|
+
|
74
92
|
def test_error_in_nested_transaction_should_retry_outermost_transaction
|
75
93
|
tries = 0
|
76
94
|
errors = 0
|
@@ -84,7 +102,7 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
84
102
|
end
|
85
103
|
end
|
86
104
|
end
|
87
|
-
|
105
|
+
|
88
106
|
assert_equal 4, tries
|
89
107
|
end
|
90
108
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: deadlock_retry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.1.
|
5
|
+
version: 1.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jamis Buck
|
@@ -11,8 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
15
|
-
default_executable:
|
14
|
+
date: 2011-05-14 00:00:00 Z
|
16
15
|
dependencies: []
|
17
16
|
|
18
17
|
description: Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL
|
@@ -32,7 +31,6 @@ files:
|
|
32
31
|
- deadlock_retry.gemspec
|
33
32
|
- lib/deadlock_retry.rb
|
34
33
|
- test/deadlock_retry_test.rb
|
35
|
-
has_rdoc: true
|
36
34
|
homepage: http://github.com/mperham/deadlock_retry
|
37
35
|
licenses: []
|
38
36
|
|
@@ -56,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
54
|
requirements: []
|
57
55
|
|
58
56
|
rubyforge_project:
|
59
|
-
rubygems_version: 1.
|
57
|
+
rubygems_version: 1.7.2
|
60
58
|
signing_key:
|
61
59
|
specification_version: 3
|
62
60
|
summary: Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL
|