Railsのエラー『ActiveRecord::ConnectionTimeoutError: could not obtain a database connection』の解決方法
Railsアプリで「ActiveRecord::ConnectionTimeoutError: could not obtain a database connection」というエラーが発生する原因と解決策について解説する。このエラーは、データベースの接続プールが枯渇したときに発生する。発生条件や調査方法、具体的な対応策をコード付きで説明する。
エラーの発生条件
このエラーは、以下のような状況で発生する。
- 同時に多数のデータベース接続が発生し、接続プールの上限を超えた
config/database.ymlのpool設定が不足している- データベースの接続が適切にクローズされていない
- マルチスレッドまたはマルチプロセスのアプリケーションで接続プールを適切に設定していない
- ワーカー(Sidekiq/Pumaなど)が過剰に動作している
エラーの発生例
Railsアプリケーションで以下のようなエラーメッセージが表示される。
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5 seconds.接続プールの設定を確認
config/database.yml の pool の設定を確認する。
production:
adapter: postgresql
encoding: unicode
pool: 5 # この値を増やす
timeout: 5000デフォルトの pool 値は 5 だが、アプリの負荷に応じて増やす。
接続数の確認
データベースの接続数を確認する。
PostgreSQL の場合:
SELECT datname, numbackends FROM pg_stat_database;MySQL の場合:
SHOW STATUS WHERE variable_name = 'Threads_connected';これらのコマンドで、現在の接続数が pool の設定を超えているか確認する。
データベース接続を適切にクローズ
長時間保持されるデータベース接続があると、接続数が枯渇する。使用後に適切に ActiveRecord::Base.connection_pool.release_connection を実行する。
ActiveRecord::Base.connection_pool.release_connectionまたは、ブロック内で確実に接続を閉じる。
ActiveRecord::Base.connection_pool.with_connection do |conn|
conn.execute("SELECT 1")
endSidekiqの並列ワーカー数を調整
Sidekiq の concurrency を制限する。
# config/sidekiq.yml
:concurrency: 10ワーカー数が多すぎると、データベース接続数を圧迫するため、適切な数に調整する。
Pumaのスレッド数を調整
Pumaのスレッド数も調整が必要。
# config/puma.rb
workers Integer(ENV.fetch("WEB_CONCURRENCY") { 2 })
threads_count = Integer(ENV.fetch("RAILS_MAX_THREADS") { 5 })
threads threads_count, threads_countスレッド数を増やしすぎるとデータベース接続が不足する可能性がある。
データベースの最大接続数を増やす
PostgreSQL の最大接続数を増やすには postgresql.conf を変更する。
max_connections = 200MySQL の場合:
SET GLOBAL max_connections = 200;本番環境では、サーバーのリソースを考慮しながら適切な値を設定する。
不要なデータベース接続を削除
Rails コンソールで未使用の接続を手動でクローズする。
ActiveRecord::Base.clear_active_connections!または、rake コマンドで一括リセット。
rails db:clear_active_connections!データベースのクエリを最適化
過剰なクエリがデータベース負荷を増やす原因となる。
N+1 問題を回避するためにincludesを使う。indexを適切に追加する。pluckやselectを活用し、不要なデータ取得を減らす。
まとめ
「ActiveRecord::ConnectionTimeoutError」はデータベース接続プールが枯渇したときに発生する。適切な pool 設定、接続の適切な管理、ワーカー数の調整、データベースの最適化によって回避できる。
-
前の記事
Vue warn: ‘$attrs is readonly’ when using Composition API の解決方法 2025.07.18
-
次の記事
PHPのエラー『Warning: Failed to Open Stream』の解決方法 2025.07.22
コメントを書く