SQLiteの本番環境への対応
Rails 8.0では、SQLiteがProduction環境で利用できるように改良されました。SQLiteといえば、2004年のリリース以来、簡易型のRDBMS(リレーショナルデータベースシステム)として位置付けられてきました。Railsにおいても、Development環境とTest環境で使うためのRDBMSとして位置付けられ、Production環境ではRails 7.1でサポートされたTrilogyをはじめ、PostgreSQL、MySQL、SQL Server、OracleといったRDBMSを用意して使うことが推奨されてきました。
改良は、SQLiteアダプタとRubyドライバに対して多くの点で実施されました。その結果、Production環境での利用に耐える性能になり、今回の変更に至りました。config/database.ymlファイルを見ると、既定でSQLiteを使用し、それはProduction環境でも変わりません。従来は、Trilogyを使う前提の設定となっていたところでした。
default: &default adapter: sqlite3 # 既定でSQLiteが使用される …略 production: primary: <<: *default database: storage/production.sqlite3 # そのままSQLiteが使用される
開発のフェーズにかかわらず同様のデータベース環境を利用できることで、いちいち本番用のデータベース環境を構築する必要がなく、開発効率を向上できます。また、後述するSQLite Solid Adapterの実装にもつながり、結果として本番環境であるDockerコンテナの構成要素をシンプルにできる効果も生まれました。
この他、以下の改善が実施されています。
- create_virtual_tableメソッドによる全文検索と仮想テーブルのサポート
- 同時実行性の向上を目的としてトランザクションは既定でIMMEDIATEモードに
- SQLite3::BusyExceptionのActiveRecord::StatementTimeoutへの変換によるエラー処理強化
[NOTE]IMMEDIATEモードとEXCLUSIVEモード
データベースのトランザクションで指定できるロックモードのことを言います。ロック中、IMMEDIATEモードでは他のユーザは読み取りのみ許可されますが、EXCLUSIVEモードでは読み書きともに許可されません。読み取りのみ許可されるIMMEDIATEモードの方が、性能が向上する可能性がありますが、読み取りが許可されることの問題が生じる可能性もあり、状況に応じた使い分けが必要となっています。
SQLite Solid Adapterの実装
Rails 8.0では、各環境の利用データベースがSQLiteに統合されたことで、Solid Adapterが利用可能になりました。
Solid Adapterとは、SQLiteを前提としたデータベースアダプタです。従来、WebSocket(Action Cable)、キャッシュ(Active Cache)、ジョブ(Active Job)については、そのバックエンドとしてPostgreSQLやMySQLといったリレーショナルデータベースに加えてオンメモリデータベースRedisを必要としていました。Rails 8.0では、これらの全てをSQLiteで置き換える3つのSolid Adapter(Solid Cable、Solid Cache、Solid Queue)によって、MySQLやRedisが必須ではなくなりました。
この背景には、SSDなどの高速なメモリストレージによって、オンメモリデータベースの必要性が低下したことがあります。また、上記のとおりRailsにおけるSQLiteデータベースの性能が向上し、Webサーバとして一般的な利用の範囲において十分に運用に耐える状況となったことも挙げられます。
3つのアダプタの導入により、config/database.ymlファイルにおいてProduction環境の設定が以下のように変わりました。モデル用に通常使用されるデータベースファイルとは別に、それぞれ専用のデータベースとマイグレーションファイルのパスが使用されます。
production: primary: # モデル用 <<: *default database: storage/production.sqlite3 cache: # Solid Cache用 <<: *default database: storage/production_cache.sqlite3 migrations_paths: db/cache_migrate queue: # Solid Queue用 <<: *default database: storage/production_queue.sqlite3 migrations_paths: db/queue_migrate cable: # Solid Cable用 <<: *default database: storage/production_cable.sqlite3 migrations_paths: db/cable_migrate
Solid Cable
Solid Cableは、Action Cableにおける新しいサブスクリプションアダプタです。Action Cableでは、Pub/Subモデルにおけるサブスクリプションの管理に、Production環境ではRedisやPostgreSQLなどの利用が推奨されてきました。SQLiteを使うSolid Cableの導入により、これらのデータベースシステムが必須でなくなります。
さらに、送信メッセージを1日間データベースに保持するので、リアルタイム更新におけるデバッグを行いやすくなるメリットもあります。Action Cableの設定ファイルであるconfig/cable.ymlにおいても、以下のようにサブスクリプションアダプタにsolid_cableを使うように設定されています。
production: adapter: solid_cable
Solid Cache
Solid Cacheは、Railsのキャッシュシステムにおける新しい保存先です。HTMLのフラグメントキャッシュは、従来はProduction環境を含めて内部メモリに記録されてきました(Production環境では必要に応じてデータベースを使う前提)。
Rails 8.0では、config/environments/production.rbファイルにおけるconfig.cache_storeの設定は、既定でSolid Cacheを使うように変更されています。
config.cache_store = :solid_cache_store
SQLiteを使うSolid Cacheによって、キャッシュ保存先をSQLiteデータベースにすることで、高速性が失われないばかりか、大きなキャッシュサイズに対するコストを抑えたキャッシュシステムを構築できるようになりました。メモリキャッシュと異なり容量に余裕があるので、キャッシュの有効期間を延ばすこともできます。
なお、キャッシュには暗号化が施され、明示的な廃棄期間によって管理しやすくなっています。プライバシーポリシーなどで定めたキャッシュ期間を反映しやすくなるといったメリットがあります。
Solid Queue
Solid Queueは、Active Jobにおける新しいキューアダプタです。Active Jobでは、ジョブのキューイングのためにResque、Delayed Job、Sidekiqといったライブラリを必要としていました(既定はSidekiq)。
Sidekiqは、バックエンドにRedisを使用するので、Active Jobの利用ではRedisの稼働が前提となっていました。SQLiteを使うSolid Queueには、堅牢な同時実行制御、失敗時の再試行とアラート、定期的なジョブスケジューリングなどの特徴があり、Sidekiqやそれが依存するRedisが必須でなくなります。
config/environments/production.rbファイルにおけるconfig.active_job.queue_adapterの設定は、既定でSolid Queueを使うように変更されています。
config.active_job.queue_adapter = :solid_queue config.solid_queue.connects_to = { database: { writing: :queue } }