Module: TransactionIsolation::ActiveRecord::ConnectionAdapters::Mysql2Adapter

Defined in:
lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb

Constant Summary collapse

VENDOR_ISOLATION_LEVEL =
{
    :read_uncommitted => 'READ UNCOMMITTED',
    :read_committed => 'READ COMMITTED',
    :repeatable_read => 'REPEATABLE READ',
    :serializable => 'SERIALIZABLE'
}
ANSI_ISOLATION_LEVEL =
{
    'READ UNCOMMITTED' => :read_uncommitted,
    'READ COMMITTED' => :read_committed,
    'REPEATABLE READ' => :repeatable_read,
    'SERIALIZABLE' => :serializable
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



8
9
10
11
12
13
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 8

def self.included( base )
  base.class_eval do
    alias_method :translate_exception_without_transaction_isolation_conflict, :translate_exception
    alias_method :translate_exception, :translate_exception_with_transaction_isolation_conflict
  end
end

Instance Method Details

#current_isolation_levelObject



33
34
35
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 33

def current_isolation_level
  ANSI_ISOLATION_LEVEL[current_vendor_isolation_level]
end

#current_vendor_isolation_levelObject



37
38
39
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 37

def current_vendor_isolation_level
  select_value( "SELECT @@session.tx_isolation" ).gsub( '-', ' ' )
end

#isolation_conflict?(exception) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
66
67
68
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 63

def isolation_conflict?( exception )
  [ "Deadlock found when trying to get lock",
    "Lock wait timeout exceeded"].any? do |error_message|
    exception.message =~ /#{Regexp.escape( error_message )}/i
  end
end

#isolation_level(level) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 41

def isolation_level( level )
  validate_isolation_level( level )

  original_vendor_isolation_level = current_vendor_isolation_level if block_given?

  execute( "SET SESSION TRANSACTION ISOLATION LEVEL #{VENDOR_ISOLATION_LEVEL[level]}" )

  begin
    yield
  ensure
    execute "SET SESSION TRANSACTION ISOLATION LEVEL #{original_vendor_isolation_level}"
  end if block_given?
end

#supports_isolation_levels?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 15

def supports_isolation_levels?
  true
end

#translate_exception_with_transaction_isolation_conflict(exception, **args) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/transaction_isolation/active_record/connection_adapters/mysql2_adapter.rb', line 55

def translate_exception_with_transaction_isolation_conflict( exception, **args )
  if isolation_conflict?( exception )
    ::ActiveRecord::TransactionIsolationConflict.new( "Transaction isolation conflict detected: #{exception.message}" )
  else
    translate_exception_without_transaction_isolation_conflict( exception, **args )
  end
end