You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ActiveRecord 7:不使用ORM模型类时如何配置并使用读写角色

ActiveRecord 7:不使用ORM模型类时如何配置并使用读写角色

嘿,这个问题我之前也折腾过!其实不用定义任何模型类,照样能搞定ActiveRecord的读写角色配置和连接切换,核心就是直接在ActiveRecord::Base本身上做文章,不用依赖抽象模型那套。

第一步:配置读写连接

首先确保你的database.yml里已经定义好了主库(写)和从库(读)的配置,比如:

# config/database.yml
primary:
  adapter: postgresql
  database: my_app_prod
  username: my_user
  password: <%= ENV['DB_PASSWORD'] %>
  host: primary.db.example.com

primary_replica:
  adapter: postgresql
  database: my_app_prod
  username: my_readonly_user
  password: <%= ENV['DB_READ_PASSWORD'] %>
  host: replica.db.example.com
  replica: true # 标记这是只读副本,ActiveRecord会自动处理只读限制

接下来在初始化代码里(比如config/initializers/active_record.rb),直接给ActiveRecord::Base配置读写角色对应的连接:

# 给ActiveRecord::Base绑定读写角色的数据库连接
ActiveRecord::Base.connects_to database: { writing: :primary, reading: :primary_replica }

第二步:在代码中选择性切换到读角色

配置好之后,你就可以用connected_to块来临时切换到读连接上下文,然后在块里用ActiveRecord::Base.connection.exec_query执行你的SQL查询——此时ActiveRecord会自动从读连接池里拿连接,执行完后也会正确回收,完全和模型类的场景一样。

示例代码:

# 执行写操作(默认用primary连接)
ActiveRecord::Base.connection.exec_query(
  "INSERT INTO users (name, email) VALUES ($1, $2)",
  "Create User",
  [[nil, "Alice"], [nil, "alice@example.com"]]
)

# 切换到读角色执行查询
ActiveRecord::Base.connected_to(role: :reading) do
  # 这里的connection会指向primary_replica
  user_results = ActiveRecord::Base.connection.exec_query(
    "SELECT name, email FROM users WHERE id = $1",
    "Fetch User",
    [[nil, 1]]
  )
  puts "Fetched user: #{user_results.rows.first.inspect}"
end

额外注意点

  • 如果你需要临时切换到写角色(比如在默认读上下文里执行写操作),只要把role: :reading改成role: :writing就行
  • 标记replica: true的连接会被ActiveRecord视为只读,如果你不小心在这个连接上执行写操作,会直接抛出错误,避免误操作
  • 连接池的管理完全由ActiveRecord自动处理,不用手动操心连接的获取和释放

备注:内容来源于stack exchange,提问作者Douglas Greenshields

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 11:14:31