mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Database adapters use a statement pool.
Database adapters use a statement pool for limiting the number of open prepared statments on the database. The limit defaults to 1000, but can be adjusted in your database config by changing 'statement_limit'.
This commit is contained in:
parent
a4fa6eab39
commit
54b7e783ef
3 changed files with 46 additions and 8 deletions
|
@ -120,7 +120,8 @@ module ActiveRecord
|
|||
|
||||
def initialize(connection, logger, connection_options, config)
|
||||
super
|
||||
@statements = StatementPool.new(@connection)
|
||||
@statements = StatementPool.new(@connection,
|
||||
config.fetch(:statement_limit) { 1000 })
|
||||
@client_encoding = nil
|
||||
connect
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'active_record/connection_adapters/abstract_adapter'
|
||||
require 'active_support/core_ext/object/blank'
|
||||
require 'active_record/connection_adapters/statement_pool'
|
||||
|
||||
# Make sure we're using pg high enough for PGResult#values
|
||||
gem 'pg', '~> 0.11'
|
||||
|
@ -246,6 +247,43 @@ module ActiveRecord
|
|||
true
|
||||
end
|
||||
|
||||
class StatementPool < ConnectionAdapters::StatementPool
|
||||
def initialize(connection, max)
|
||||
super
|
||||
@counter = 0
|
||||
@cache = {}
|
||||
end
|
||||
|
||||
def each(&block); @cache.each(&block); end
|
||||
def key?(key); @cache.key?(key); end
|
||||
def [](key); @cache[key]; end
|
||||
def length; @cache.length; end
|
||||
|
||||
def next_key
|
||||
"a#{@counter + 1}"
|
||||
end
|
||||
|
||||
def []=(sql, key)
|
||||
while @max <= @cache.size
|
||||
dealloc(@cache.shift.last)
|
||||
end
|
||||
@counter += 1
|
||||
@cache[sql] = key
|
||||
end
|
||||
|
||||
def clear
|
||||
@cache.each_value do |stmt_key|
|
||||
dealloc stmt_key
|
||||
end
|
||||
@cache.clear
|
||||
end
|
||||
|
||||
private
|
||||
def dealloc(key)
|
||||
@connection.query "DEALLOCATE #{key}"
|
||||
end
|
||||
end
|
||||
|
||||
# Initializes and connects a PostgreSQL adapter.
|
||||
def initialize(connection, logger, connection_parameters, config)
|
||||
super(connection, logger)
|
||||
|
@ -254,9 +292,10 @@ module ActiveRecord
|
|||
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
||||
@local_tz = nil
|
||||
@table_alias_length = nil
|
||||
@statements = {}
|
||||
|
||||
connect
|
||||
@statements = StatementPool.new @connection,
|
||||
config.fetch(:statement_limit) { 1000 }
|
||||
|
||||
if postgresql_version < 80200
|
||||
raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!"
|
||||
|
@ -271,9 +310,6 @@ module ActiveRecord
|
|||
|
||||
# Clears the prepared statements cache.
|
||||
def clear_cache!
|
||||
@statements.each_value do |value|
|
||||
@connection.query "DEALLOCATE #{value}"
|
||||
end
|
||||
@statements.clear
|
||||
end
|
||||
|
||||
|
@ -996,7 +1032,7 @@ module ActiveRecord
|
|||
|
||||
def exec_cache(sql, binds)
|
||||
unless @statements.key? sql
|
||||
nextkey = "a#{@statements.length + 1}"
|
||||
nextkey = @statements.next_key
|
||||
@connection.prepare nextkey, sql
|
||||
@statements[sql] = nextkey
|
||||
end
|
||||
|
|
|
@ -50,7 +50,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
class StatementPool < ConnectionAdapters::StatementPool
|
||||
def initialize(connection, max = 1000)
|
||||
def initialize(connection, max)
|
||||
super
|
||||
@cache = {}
|
||||
end
|
||||
|
@ -82,7 +82,8 @@ module ActiveRecord
|
|||
|
||||
def initialize(connection, logger, config)
|
||||
super(connection, logger)
|
||||
@statements = StatementPool.new(@connection)
|
||||
@statements = StatementPool.new(@connection,
|
||||
config.fetch(:statement_limit) { 1000 })
|
||||
@config = config
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue