1
0
Fork 0
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:
Matthew Draper 2016-10-27 15:31:22 -05:00
parent 928f46621c
commit 007e50d8e5
5 changed files with 47 additions and 25 deletions

View file

@ -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

View file

@ -86,7 +86,9 @@ module ActiveRecord
end
begin
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
result = stmt.execute(*type_casted_binds)
end
rescue Mysql2::Error => e
if cache_stmt
@statements.delete(sql)

View file

@ -85,9 +85,11 @@ module ActiveRecord
# Queries the database and returns the results in an Array-like object
def query(sql, name = nil) #:nodoc:
log(sql, name) do
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
result_as_array @connection.async_exec(sql)
end
end
end
# Executes an SQL statement, returning a PG::Result object on success
# or raising a PG::Error exception otherwise.
@ -95,9 +97,11 @@ module ActiveRecord
# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.
def execute(sql, name = nil)
log(sql, name) do
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@connection.async_exec(sql)
end
end
end
def exec_query(sql, name = "SQL", binds = [], prepare: false)
execute_and_clear(sql, name, binds, prepare: prepare) do |result|

View file

@ -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,8 +613,10 @@ module ActiveRecord
type_casted_binds = type_casted_binds(binds)
log(sql, name, binds, type_casted_binds, stmt_key) do
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)

View file

@ -191,6 +191,7 @@ module ActiveRecord
type_casted_binds = type_casted_binds(binds)
log(sql, name, binds, type_casted_binds) do
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
# Don't cache statements if they are not prepared
unless prepare
stmt = @connection.prepare(sql)
@ -213,6 +214,7 @@ module ActiveRecord
stmt.bind_params(type_casted_binds)
records = stmt.to_a
end
end
ActiveRecord::Result.new(cols, records)
end
@ -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: