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
相关产品推荐
相关产品推荐

