Rails项目怎么配置PostgreSQL数据库连接

文章导读
Rails 项目接 PostgreSQL,真正要动的地方通常只有两处:Gemfile 里的 pg 驱动,和 config/database.yml(或者用 DATABASE_URL 覆盖它)。卡住人的往往不是 yml 怎么写,而是没先确认三件事:PostgreSQL 服务是否已在监听、pg gem 在本机能不能编译、连接用的账号有没有建库建表权限。这三件事任何一条不成立,改 yml 都只是白改。
📋 目录
  1. 壹 先确认当前场景和目标
  2. 贰 按这个顺序处理
  3. 叁 改完后怎么验证
  4. 肆 容易忽略的边界
A A

Rails 项目接 PostgreSQL,真正要动的地方通常只有两处:Gemfile 里的 pg 驱动,和 config/database.yml(或者用 DATABASE_URL 覆盖它)。卡住人的往往不是 yml 怎么写,而是没先确认三件事:PostgreSQL 服务是否已在监听、pg gem 在本机能不能编译、连接用的账号有没有建库建表权限。这三件事任何一条不成立,改 yml 都只是白改。

判断方向:先确认 PostgreSQL 服务可连、pg gem 能装上、账号有建库权限,再动 database.yml。适用场景是本地开发或自建数据库的常规 Rails 项目;验证信号是 rails db:prepare 正常结束、ActiveRecord::Base.connection.active? 返回 true、psql 能看到同名数据库。边界:托管数据库、强制 SSL、连接数受限的环境要按服务方给的参数补 sslmode、pool 和 URL,不能直接套本地示例。

先确认当前场景和目标

动手前先分清两种场景,处理方式不同:新建项目可以在 rails new myapp -d postgresql 时就选定数据库适配器,生成的 database.yml 已经是 PostgreSQL 结构;已有项目从 SQLite 或 MySQL 迁过来,则要同时改 Gemfile 和 yml,并且原来 db/*.sqlite3 里的数据不会自动搬过去。

需要先确认的信息,建议逐条落实:

  • PostgreSQL 是跑在本机、同一台机器的容器里,还是远程实例;主机名和端口(默认 5432)分别是什么。
  • 连接方式是 TCP(host + port)还是本地 Unix socket(host 留空或写 socket 目录);两者对应的认证方式在 pg_hba.conf 里不一样。
  • 所用账号是否有 CREATEDB 权限,否则 rails db:create 会失败。
  • Rails 版本决定 yml 结构:较新版本默认带 default: &default 锚点和 primary 之类的层级,旧版本是平铺的。拿现有文件改,比凭记忆重写更稳。
  • 是否有环境变量注入(DATABASE_URL),它会覆盖 yml 中同名配置,容易被忽略。

按这个顺序处理

第一步,在 Gemfile 里确保驱动正确。SQLite 项目要把 gem "sqlite3" 换成 gem "pg",然后执行 bundle install。如果这一步在编译阶段报错,通常缺的是 PostgreSQL 客户端开发库,Debian/Ubuntu 系可先装 libpq-dev,macOS 用 Homebrew 安装 postgresql 后一般会带齐。

Rails项目怎么配置PostgreSQL数据库连接
# Gemfile
source "https://rubygems.org"

gem "rails"
gem "pg"        # 原来可能是 gem "sqlite3"

第二步,改 config/database.yml。下面是一份可替换的通用骨架,host、username、password、database 按实际环境替换;本地 socket 连接时把 host 和 port 两行删掉即可。不要把真实密码提交进仓库,建议走环境变量。

default: &default
  adapter: postgresql
  encoding: unicode
  host: <%= ENV.fetch("PGHOST", "127.0.0.1") %>
  port: <%= ENV.fetch("PGPORT", 5432) %>
  username: <%= ENV.fetch("PGUSER", "postgres") %>
  password: <%= ENV.fetch("PGPASSWORD", "") %>
  pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5) %>

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production

第三步,建库并跑迁移。顺序建议是 bin/rails db:create 先确认能连上并创建数据库,再 bin/rails db:migrate。Rails 较新版本提供 bin/rails db:prepare 一次性完成建库、加载 schema 和迁移,本地新环境用它更省事。如果部署环境习惯用单个连接串,也可以只设置 DATABASE_URL=postgresql://user:pass@host:5432/myapp_production,再在 yml 里保留 adapter: postgresql 作为适配器声明;两者冲突时以 URL 为准,这点需要结合所用 Rails 版本确认。

改完后怎么验证

不要只看命令退出码,按下面几层依次确认,能更快定位问题出在连接、权限还是迁移。

  1. 直接用客户端确认服务可达:psql -h 127.0.0.1 -p 5432 -U postgres -l,能列出数据库说明网络和账号认证都通了。
  2. 在项目目录执行 bin/rails runner "puts ActiveRecord::Base.connection.active?",输出 true 表示 Rails 侧连接池已成功建立连接。
  3. 执行 bin/rails db:migrate:status,能看到迁移列表且状态为 up,说明当前连的是预期数据库,而不是误连到别的库。
  4. 启动 bin/rails server 访问一个会查库的页面,同时观察 log/development.log,日志里应出现针对 PostgreSQL 的 SQL 语句;如果日志里仍是 SQLite 语句,多半是 Gemfile 或 yml 没生效,需要检查是否还有残留的 sqlite3 配置。

预期信号可以归纳为:命令不报连接错误、迁移状态可读、日志出现 PG 风格 SQL。三者缺一,就回到对应层的配置上查,不必继续往下改。

Rails项目怎么配置PostgreSQL数据库连接

容易忽略的边界

几个常见限制值得提前知道。其一,本地 Unix socket 连接在部分系统上默认走 peer 认证,用系统用户名登录,yml 里写的 username 可能不生效,这时要么改用 TCP 并配置密码认证,要么建立同名数据库角色。其二,pg gem 的编译依赖 libpq,CI 或精简镜像里缺库会直接导致 bundle install 失败,需要在镜像构建阶段补上开发包。

其三,pool 值不是越大越好,它要和应用进程数、数据库允许的最大连接数一起看,超出上限时表现为连接超时而不是明确报错。其四,若项目使用 structure.sql 而非 schema.rb,迁移和加载都依赖 pg_dump,客户端版本与服务器版本差异过大时可能失败,这类环境建议固定客户端版本。其五,托管数据库常要求 SSL,需要在 yml 或 URL 中补 sslmode=require,否则报连接被拒绝但信息不明显。

回退建议:改动前先备份现有的 config/database.yml 和 Gemfile.lock;如果迁移后发现连错库或驱动冲突,先还原这两个文件、执行 bundle install,再逐步定位,不要在多个配置同时改动的情况下排查。对于仍在用 SQLite 且数据量不大的本地项目,短期内保留 SQLite 跑开发、只在需要 PostgreSQL 特性时切换,也是一种可接受的过渡做法,但两套环境的行为差异要自己心里有数。