ベトナムから来て、2年間GA technologiesで働いている24歳のアンと申します。RailsエンジニアとしてRENOSYのバックエンドを担当しています。今回仕事に関係があるためRails 6でマルチDBの対応方法を勉強しましたので理解できたものをおまとめさせていただきたいと思います。
1. マルチDBとは
一つのアプリケーションから、複数DBにアクセスしてデータを読み書きをできるようにする仕組みです。
2. なぜマルチDBを使うのか
プロジェクトの規模が大きくなって、複数データベースを対応する必要が発生することがあります。主に以下の2つのユースケースがあると思います。
- 新しいシステムで既存のDBも使いたい
- スピード改善またはデータ安全性を向上するため、読み取り専用のレプリカを使いたい
今回、開発しているシステムは以下のような構成になっています。
- 管理者向けのCMSシステムで配信するコンテンツの登録を行います。
- 一般ユーザー向けのWebアプリケーション(登録されたコンテンツを表示する) が複数あります。
このシステムを実現するために、マルチDBを使用しました。以下のようなシステム構成になります。
3. なぜ Rails 6
Rails 6から公式にマルチDBに対応するようになりました。その機能を活用すると簡単に実装できます。
Railsガイドも共有です。https://edgeguides.rubyonrails.org/active_record_multiple_databases.html
4. マルチDBを使うための手順
では、マルチDBを使うための手順を、ローカル環境におけるサンプルの構築を例として、下記に説明します
4.1 設定ファイルの編集
仮に今の データベース(config/database.yml
)はこんな感じです。
default: &default adapter: mysql2 development: <<: *default database: primary_development
やりたいのは、以下の2つです。
4.1.1 primaryのレプリカを追加
- 以下の感じで
database.yml
ファイルを編集します。レプリカの場合replica: true
を指定します。
default: &default adapter: mysql2 development: # developmentの環境でマルチDB情報を書きます。 primary: <<: *default database: primary_development migrations_paths: "db/migrate/primary" primary_replica: <<: *default database: primary_development # この場合、MasterとSlave DBは同じホストですが、別のポートです。 port: 3307 # 違うユーザー名で読み取りのみ権限であるべき。 username: my_readonly_user password: my_readonly_password replica: true
application_record.rb
を更新します
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true # 接続情報を指定 connects_to database: { writing: :primary, reading: :primary_replica } end
4.1.2 secondのデータベース追加
database.yml
にsecond DBを追加します
default: &default adapter: mysql2 development: primary: <<: *default database: primary_development migrations_paths: "db/migrate/primary" primary_replica: <<: *default database: primary_development # この場合、MasterとSlave DBは同じホストですが、別のポートです。 port: 3307 # 違うユーザー名で読み取りのみ権限であるべき。 username: my_readonly_user password: my_readonly_password replica: true # secondDBの接続情報を書きます。 second: <<: *default migrations_paths: "db/migrate/second" database: second_development second_replica: <<: *default database: second_development # この場合、MasterとSlave DBは同じホストですが、別のポートです。 port: 3307 # 違うユーザー名で読み取りのみ権限です。 username: my_readonly_user password: my_readonly_password replica: true
SecondBaseApplicationRecord
を作ります。Secondのモデルだったら、このSecondBaseApplicationRecord
を継承します。もちろん、secondの接続情報も指定する必要があります
class SecondBaseApplicationRecord < ActiveRecord::Base self.abstract_class = true # secondの接続情報も指定する connects_to database: {reading: :second_replica, writing: :second} end
4.2 コマンドの実行
Railsのマイグレーションの実行もマルチDBに対応していて、以下のように切り替えたり同時に実行できたりします。
4.2.1 データベースを作る
- primaryだけデータベースを作る場合:
rails db:create:primary
- secondだけデータベースを作る場合:
rails db:create:second
- 全てのデータベースを作る場合 :
rails db:create
4.2.2 モデルを作る
例えば、primaryにUserモデルを作ったら下記のコマンドで実行できます。
rails g model User name:string --database primary
--database
オプションでデータベースを指定する必要あります。migrateファイルは相当のフォルダーに分けられます。この場合db/migrate/primary
のようになります。Secondデータベースのモデルを作るのも同じようにやりますが、SecondBaseApplicationRecord
を継承するように変更忘れないようにご留意ください。
フォルダ構造は画像のようです。
4.2.3 migrateを実行する
データベースの作成と同じように DBを指定できます
- primaryだけmigrateする場合:
rails db:migrate:primary
- secondだけmigrateする場合:
rails db:migrate:second
- 全てmigrateする場合 :
rails db:migrate
5. Rails 6のマルチDB対応をしてみた感想
Rails 6以前はマルチDBを対応できないわけではないですが、公式にサポートされたので、簡単に実装できました。さらに、下記のPRから推測できるように、今後、公式のドキュメントも整備されることが期待されるので安心で実装できると思います。
Document multiple databases in Rails by eileencodes · Pull Request #36389 · rails/rails · GitHub