mirror of https://github.com/rails/rails
AbstractAdapter: only synchronize when necessary
Ref: https://github.com/rails/rails/pull/28083 Right now all database operations are synchronized with a monitor even though it's useless in the vast majority of cases. The synchronization is only useful when transactional fixtures are enabled. In production, connections are never shared across threads, as such this extra synchronization is wasteful.
This commit is contained in:
parent
625e29211c
commit
1a2ca1920c
|
@ -173,6 +173,10 @@ module ActiveRecord
|
|||
else
|
||||
@lock_thread = nil
|
||||
end
|
||||
|
||||
if (active_connection = @thread_cached_conns[connection_cache_key(current_thread)])
|
||||
active_connection.synchronized = lock_thread
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieve the connection associated with the current thread, or call
|
||||
|
@ -352,7 +356,9 @@ module ActiveRecord
|
|||
# Raises:
|
||||
# - ActiveRecord::ConnectionTimeoutError no connection can be obtained from the pool.
|
||||
def checkout(checkout_timeout = @checkout_timeout)
|
||||
checkout_and_verify(acquire_connection(checkout_timeout))
|
||||
connection = checkout_and_verify(acquire_connection(checkout_timeout))
|
||||
connection.synchronized = @lock_thread
|
||||
connection
|
||||
end
|
||||
|
||||
# Check-in a database connection back into the pool, indicating that you
|
||||
|
|
|
@ -4,6 +4,7 @@ require "set"
|
|||
require "active_record/connection_adapters/sql_type_metadata"
|
||||
require "active_record/connection_adapters/abstract/schema_dumper"
|
||||
require "active_record/connection_adapters/abstract/schema_creation"
|
||||
require "active_support/concurrency/null_lock"
|
||||
require "active_support/concurrency/load_interlock_aware_monitor"
|
||||
require "arel/collectors/bind"
|
||||
require "arel/collectors/composite"
|
||||
|
@ -155,7 +156,7 @@ module ActiveRecord
|
|||
@idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||
@visitor = arel_visitor
|
||||
@statements = build_statement_pool
|
||||
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
||||
self.synchronized = false
|
||||
|
||||
@prepared_statements = self.class.type_cast_config_to_boolean(
|
||||
@config.fetch(:prepared_statements) { default_prepared_statements }
|
||||
|
@ -171,6 +172,14 @@ module ActiveRecord
|
|||
@verified = false
|
||||
end
|
||||
|
||||
def synchronized=(synchronized) # :nodoc:
|
||||
@lock = if synchronized
|
||||
ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
||||
else
|
||||
ActiveSupport::Concurrency::NullLock
|
||||
end
|
||||
end
|
||||
|
||||
EXCEPTION_NEVER = { Exception => :never }.freeze # :nodoc:
|
||||
EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze # :nodoc:
|
||||
private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ActiveSupport
|
||||
module Concurrency
|
||||
module NullLock # :nodoc:
|
||||
extend self
|
||||
|
||||
def synchronize
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue