Active Record 连接处理
- C
- E
- L
- P
- R
- S
- W
常量
DEFAULT_ENV | = | -> { RAILS_ENV.call || "default_env" } |
RAILS_ENV | = | -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence } |
属性
[W] | connection_specification_name |
实例公有方法
clear_query_caches_for_current_thread() 链接
清除与当前线程关联的所有连接的查询缓存。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 258 def clear_query_caches_for_current_thread connection_handler.each_connection_pool do |pool| pool.clear_query_cache end end
connected?() 链接
如果 Active Record 已连接,则返回 true
。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 351 def connected? connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard) end
connected_to(role: nil, shard: nil, prevent_writes: false, &blk) 链接
在代码块的持续时间内连接到一个角色(例如写入、读取或自定义角色)和/或分片。在代码块结束时,连接将返回到原始角色/分片。
如果只传递一个角色,Active Record 将根据请求的角色查找连接。如果请求了未建立的角色,则会引发 ActiveRecord::ConnectionNotEstablished
错误
ActiveRecord::Base.connected_to(role: :writing) do
Dog.create! # creates dog using dog writing connection
end
ActiveRecord::Base.connected_to(role: :reading) do
Dog.create! # throws exception because we're on a replica
end
切换到分片时,必须也传递角色。如果传递了不存在的分片,则会引发 ActiveRecord::ConnectionNotEstablished
错误。
当传递分片和角色时,Active Record 将首先查找角色,然后根据分片键查找连接。
ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
Dog.first # finds first Dog record stored on the shard one replica
end
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 136 def connected_to(role: nil, shard: nil, prevent_writes: false, &blk) if self != Base && !abstract_class raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes." end if !connection_class? && !primary_class? raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection." end unless role || shard raise ArgumentError, "must provide a `shard` and/or `role`." end with_role_and_shard(role, shard, prevent_writes, &blk) end
connected_to?(role:, shard: ActiveRecord::Base.default_shard) 链接
如果角色是当前连接的角色和/或当前连接的分片,则返回 true。如果没有传递分片,将使用默认分片。
ActiveRecord::Base.connected_to(role: :writing) do
ActiveRecord::Base.connected_to?(role: :writing) #=> true
ActiveRecord::Base.connected_to?(role: :reading) #=> false
end
ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
end
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 253 def connected_to?(role:, shard: ActiveRecord::Base.default_shard) current_role == role.to_sym && current_shard == shard.to_sym end
connected_to_all_shards(role: nil, prevent_writes: false, &blk) 链接
将代码块传递给每个 shard
的 connected_to
(如果有的话),并将结果保存在一个数组中。
可以选择传递 role
和/或 prevent_writes
,它们将被转发到每个 connected_to
调用。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 186 def connected_to_all_shards(role: nil, prevent_writes: false, &blk) shard_keys.map do |shard| connected_to(shard: shard, role: role, prevent_writes: prevent_writes, &blk) end end
connected_to_many(*classes, role:, shard: nil, prevent_writes: false) 链接
将角色和/或分片连接到提供的连接名称。可以选择传递 prevent_writes
来阻止连接上的写入。reading
将自动将 prevent_writes
设置为 true。
connected_to_many
是 connected_to
代码块的深度嵌套的替代方案。
用法
ActiveRecord::Base.connected_to_many(AnimalsRecord, MealsRecord, role: :reading) do
Dog.first # Read from animals replica
Dinner.first # Read from meals replica
Person.first # Read from primary writer
end
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 165 def connected_to_many(*classes, role:, shard: nil, prevent_writes: false) classes = classes.flatten if self != Base || classes.include?(Base) raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base." end prevent_writes = true if role == ActiveRecord.reading_role append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes) yield ensure connected_to_stack.pop end
connecting_to(role: default_role, shard: default_shard, prevent_writes: false) 链接
使用指定的连接。
此方法对于确保正在使用特定连接非常有用。例如,在只读模式下启动控制台时。
不建议在请求中使用此方法,因为它不像 connected_to
那样生成代码块。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 199 def connecting_to(role: default_role, shard: default_shard, prevent_writes: false) prevent_writes = true if role == ActiveRecord.reading_role append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self]) end
connection() 链接
已弃用。请改用 #with_connection
或 #lease_connection
。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 274 def connection pool = connection_pool if pool.permanent_lease? case ActiveRecord.permanent_connection_checkout when :deprecated ActiveRecord.deprecator.warn <<~MESSAGE Called deprecated `ActiveRecord::Base.connection` method. Either use `with_connection` or `lease_connection`. MESSAGE when :disallowed raise ActiveRecordError, <<~MESSAGE Called deprecated `ActiveRecord::Base.connection` method. Either use `with_connection` or `lease_connection`. MESSAGE end pool.lease_connection else pool.active_connection end end
connection_db_config() 链接
返回关联连接的 db_config 对象
ActiveRecord::Base.connection_db_config
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
@name="primary", @config={pool: 5, timeout: 5000, database: "storage/development.sqlite3", adapter: "sqlite3"}>
仅用于读取。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 334 def connection_db_config connection_pool.db_config end
connection_pool() 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 342 def connection_pool connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true) end
connection_specification_name() 链接
返回当前类或其父类的连接规范名称。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 316 def connection_specification_name if @connection_specification_name.nil? return self == Base ? Base.name : superclass.connection_specification_name end @connection_specification_name end
connects_to(database: {}, shards: {}) 链接
将模型连接到指定的数据库。database
关键字接受一个包含 role
和 database_key
的哈希。
这将使用 database_key
查找数据库配置,并建立与该配置的连接。
class AnimalsModel < ApplicationRecord
self.abstract_class = true
connects_to database: { writing: :primary, reading: :primary_replica }
end
connects_to
也支持水平分片。水平分片 API 也支持只读副本。您可以将模型连接到如下所示的分片列表
class AnimalsModel < ApplicationRecord
self.abstract_class = true
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
shard_two: { writing: :primary_shard_two, reading: :primary_shard_replica_two }
}
end
返回一个数据库连接数组。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 81 def connects_to(database: {}, shards: {}) raise NotImplementedError, "`connects_to` can only be called on ActiveRecord::Base or abstract classes" unless self == Base || abstract_class? if database.present? && shards.present? raise ArgumentError, "`connects_to` can only accept a `database` or `shards` argument, but not both arguments." end connections = [] @shard_keys = shards.keys if shards.empty? shards[:default] = database end self.default_shard = shards.keys.first shards.each do |shard, database_keys| database_keys.each do |role, database_key| db_config = resolve_config_for_connection(database_key) self.connection_class = true connections << connection_handler.establish_connection(db_config, owner_name: self, role: role, shard: shard.to_sym) end end connections end
establish_connection(config_or_env = nil) 链接
建立与数据库的连接。接受一个哈希作为输入,其中 :adapter
键必须指定一个数据库适配器的名称(小写),例如对于常规数据库(MySQL、PostgreSQL 等)
ActiveRecord::Base.establish_connection(
adapter: "mysql2",
host: "localhost",
username: "myuser",
password: "mypass",
database: "somedatabase"
)
SQLite 数据库的示例
ActiveRecord::Base.establish_connection(
adapter: "sqlite3",
database: "path/to/dbfile"
)
也接受键作为字符串(例如,用于从 YAML 中解析)
ActiveRecord::Base.establish_connection(
"adapter" => "sqlite3",
"database" => "path/to/dbfile"
)
或 URL
ActiveRecord::Base.establish_connection(
"postgres://myuser:mypass@localhost/somedatabase"
)
如果 ActiveRecord::Base.configurations 已设置(Rails 会自动将 config/database.yml 的内容加载到其中),则也可以使用符号作为参数,表示配置哈希中的键
ActiveRecord::Base.establish_connection(:production)
在发生错误时,可能会返回 AdapterNotSpecified
、AdapterNotFound
和 ArgumentError
异常。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 50 def establish_connection(config_or_env = nil) config_or_env ||= DEFAULT_ENV.call.to_sym db_config = resolve_config_for_connection(config_or_env) connection_handler.establish_connection(db_config, owner_name: self, role: current_role, shard: current_shard) end
lease_connection() 链接
返回当前与类关联的连接。这也可以用于“借用”连接来完成与任何特定 Active Record 无关的数据库工作。连接将在整个请求或作业持续时间内保持租赁状态,或者直到调用 #release_connection
。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 269 def lease_connection connection_pool.lease_connection end
prohibit_shard_swapping(enabled = true) 链接
禁止在传递的代码块内交换分片。
在某些情况下,您可能希望能够交换分片,但不允许嵌套调用 connected_to
或 connected_to_many
再次交换。这在使用分片提供每个请求数据库隔离的情况下非常有用。
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 211 def prohibit_shard_swapping(enabled = true) prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled yield ensure ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value end
release_connection() 链接
将当前租赁的连接返回到池中
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 298 def release_connection connection_pool.release_connection end
remove_connection() 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 355 def remove_connection name = @connection_specification_name if defined?(@connection_specification_name) # if removing a connection that has a pool, we reset the # connection_specification_name so it will use the parent # pool. if connection_handler.retrieve_connection_pool(name, role: current_role, shard: current_shard) self.connection_specification_name = nil end connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard) end
retrieve_connection() 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 346 def retrieve_connection connection_handler.retrieve_connection(connection_specification_name, role: current_role, shard: current_shard) end
shard_keys() 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 376 def shard_keys connection_class_for_self.instance_variable_get(:@shard_keys) || [] end
shard_swapping_prohibited?() 链接
确定当前是否禁止交换分片
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 220 def shard_swapping_prohibited? ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] end
sharded?() 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 380 def sharded? shard_keys.any? end
while_preventing_writes(enabled = true, &block) 链接
无论角色如何,都阻止写入数据库。
在某些情况下,您可能希望阻止写入数据库,即使您是在可以写入数据库的数据库上。while_preventing_writes
将阻止在块持续时间内写入数据库。
此方法不提供与只读用户相同的保护,旨在防止意外写入。
请参阅 READ_QUERY
以了解此方法阻止的查询。
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 235 def while_preventing_writes(enabled = true, &block) connected_to(role: current_role, prevent_writes: enabled, &block) end
with_connection(prevent_permanent_checkout: false, &block) 链接
从连接池中检出连接,将其传递给块,然后将其检入。如果连接已通过 lease_connection
或对 with_connection
的父级调用租用,则将传递相同的连接。如果在块内调用 lease_connection
,则连接不会被检入。如果在块内调用 connection
,则连接不会被检入,除非 prevent_permanent_checkout
参数设置为 true
。
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_handling.rb, line 309 def with_connection(prevent_permanent_checkout: false, &block) connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block) end