Class: SolidObjects::DatabaseAdapters::Mysql
Constant Summary
SolidObjects::DatabaseAdapter::TRANSACTION_CLOCK, SolidObjects::DatabaseAdapter::TRANSACTION_CLOCK_SCOPE
Instance Attribute Summary
#connection_pool, #fixed_connection
Instance Method Summary
collapse
#configure_transaction_deadline, #database_now, for, #initialize, #lock_candidates, #read_database_now, #server_version, #transaction, #unsupported_server_reasons, #with_connection, #with_lock_probe, #with_lock_retry, #with_transaction_clock
Instance Method Details
#additional_server_reasons ⇒ Array[String]
A non-transactional engine would silently break fenced commits, so the
storage engine is verified rather than assumed.
19
20
21
22
23
24
25
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 19
def additional_server_reasons
tables = non_innodb_tables
return [] if tables.empty?
[ "these Solid Objects tables do not use InnoDB, so their commits are " \
"not transactional: #{tables.join(", ")}" ]
end
|
#claim_lock ⇒ String
12
13
14
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 12
def claim_lock
"FOR UPDATE SKIP LOCKED"
end
|
#current_time_expression ⇒ String
45
46
47
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 45
def current_time_expression
"CURRENT_TIMESTAMP(6)"
end
|
#deadline_error?(error) ⇒ Boolean
82
83
84
85
86
87
88
89
90
91
92
93
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 82
def deadline_error?(error)
return false unless SyncDeadline.active?
return true if error.is_a?(ActiveRecord::LockWaitTimeout)
cause = error
while cause
return true if cause.respond_to?(:error_number) && cause.error_number == 3024
cause = cause.cause
end
false
end
|
#minimum_server_version ⇒ Gem::Version?
40
41
42
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 40
def minimum_server_version
Gem::Version.new("8.0")
end
|
#non_innodb_tables ⇒ Array[String]
28
29
30
31
32
33
34
35
36
37
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 28
def non_innodb_tables
names = SolidObjects::Doctor::EXPECTED_COLUMNS.keys.map { |name| SolidObjects.table_name(name) }
with_connection do |connection|
connection.select_rows(<<~SQL.squish).filter_map { |table, engine| table if engine != "InnoDB" }
SELECT table_name, engine FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name IN (#{names.map { |name| connection.quote(name) }.join(", ")})
SQL
end
end
|
#supports_skip_locked? ⇒ Boolean
7
8
9
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 7
def supports_skip_locked?
true
end
|
#with_transaction_deadline(connection) { ... } ⇒ Object
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
# File 'lib/solid_objects/database_adapters/mysql.rb', line 52
def with_transaction_deadline(connection)
return yield unless SyncDeadline.active?
previous_lock_timeout = connection.select_value(
"SELECT @@SESSION.innodb_lock_wait_timeout"
).to_i
previous_execution_timeout = connection.select_value(
"SELECT @@SESSION.max_execution_time"
).to_i
connection.execute(
"SET SESSION innodb_lock_wait_timeout = #{SyncDeadline.remaining_seconds}"
)
connection.execute(
"SET SESSION max_execution_time = #{SyncDeadline.remaining_milliseconds}"
)
yield
ensure
if previous_lock_timeout
connection.execute(
"SET SESSION innodb_lock_wait_timeout = #{previous_lock_timeout}"
)
end
if previous_execution_timeout
connection.execute(
"SET SESSION max_execution_time = #{previous_execution_timeout}"
)
end
end
|