mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Permit loads while queries are running
A query may wait on a database-level lock, which could lead to a deadlock between threads.
This commit is contained in:
parent
928f46621c
commit
007e50d8e5
5 changed files with 47 additions and 25 deletions
|
@ -215,7 +215,11 @@ module ActiveRecord
|
|||
|
||||
# Executes the SQL statement in the context of this connection.
|
||||
def execute(sql, name = nil)
|
||||
log(sql, name) { @connection.query(sql) }
|
||||
log(sql, name) do
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
@connection.query(sql)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Mysql2Adapter doesn't have to free a result after using it, but we use this method
|
||||
|
|
|
@ -86,7 +86,9 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
begin
|
||||
result = stmt.execute(*type_casted_binds)
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
result = stmt.execute(*type_casted_binds)
|
||||
end
|
||||
rescue Mysql2::Error => e
|
||||
if cache_stmt
|
||||
@statements.delete(sql)
|
||||
|
|
|
@ -85,7 +85,9 @@ module ActiveRecord
|
|||
# Queries the database and returns the results in an Array-like object
|
||||
def query(sql, name = nil) #:nodoc:
|
||||
log(sql, name) do
|
||||
result_as_array @connection.async_exec(sql)
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
result_as_array @connection.async_exec(sql)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -95,7 +97,9 @@ module ActiveRecord
|
|||
# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.
|
||||
def execute(sql, name = nil)
|
||||
log(sql, name) do
|
||||
@connection.async_exec(sql)
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
@connection.async_exec(sql)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -601,7 +601,11 @@ module ActiveRecord
|
|||
|
||||
def exec_no_cache(sql, name, binds)
|
||||
type_casted_binds = type_casted_binds(binds)
|
||||
log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) }
|
||||
log(sql, name, binds, type_casted_binds) do
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
@connection.async_exec(sql, type_casted_binds)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exec_cache(sql, name, binds)
|
||||
|
@ -609,7 +613,9 @@ module ActiveRecord
|
|||
type_casted_binds = type_casted_binds(binds)
|
||||
|
||||
log(sql, name, binds, type_casted_binds, stmt_key) do
|
||||
@connection.exec_prepared(stmt_key, type_casted_binds)
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
@connection.exec_prepared(stmt_key, type_casted_binds)
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::StatementInvalid => e
|
||||
raise unless is_cached_plan_failure?(e)
|
||||
|
|
|
@ -191,27 +191,29 @@ module ActiveRecord
|
|||
type_casted_binds = type_casted_binds(binds)
|
||||
|
||||
log(sql, name, binds, type_casted_binds) do
|
||||
# Don't cache statements if they are not prepared
|
||||
unless prepare
|
||||
stmt = @connection.prepare(sql)
|
||||
begin
|
||||
cols = stmt.columns
|
||||
unless without_prepared_statement?(binds)
|
||||
stmt.bind_params(type_casted_binds)
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
# Don't cache statements if they are not prepared
|
||||
unless prepare
|
||||
stmt = @connection.prepare(sql)
|
||||
begin
|
||||
cols = stmt.columns
|
||||
unless without_prepared_statement?(binds)
|
||||
stmt.bind_params(type_casted_binds)
|
||||
end
|
||||
records = stmt.to_a
|
||||
ensure
|
||||
stmt.close
|
||||
end
|
||||
else
|
||||
cache = @statements[sql] ||= {
|
||||
stmt: @connection.prepare(sql)
|
||||
}
|
||||
stmt = cache[:stmt]
|
||||
cols = cache[:cols] ||= stmt.columns
|
||||
stmt.reset!
|
||||
stmt.bind_params(type_casted_binds)
|
||||
records = stmt.to_a
|
||||
ensure
|
||||
stmt.close
|
||||
end
|
||||
else
|
||||
cache = @statements[sql] ||= {
|
||||
stmt: @connection.prepare(sql)
|
||||
}
|
||||
stmt = cache[:stmt]
|
||||
cols = cache[:cols] ||= stmt.columns
|
||||
stmt.reset!
|
||||
stmt.bind_params(type_casted_binds)
|
||||
records = stmt.to_a
|
||||
end
|
||||
|
||||
ActiveRecord::Result.new(cols, records)
|
||||
|
@ -229,7 +231,11 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def execute(sql, name = nil) #:nodoc:
|
||||
log(sql, name) { @connection.execute(sql) }
|
||||
log(sql, name) do
|
||||
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
||||
@connection.execute(sql)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def begin_db_transaction #:nodoc:
|
||||
|
|
Loading…
Reference in a new issue