做后端开发这些年,我见过太多项目因为数据库选型不当或者配置错误,上线后直接被流量压垮。前阵子有个朋友跑来找我,说他们的 MySQL 扛不住高并发,问我怎么办。我只问了一句:"试过 PostgreSQL 没有?"
他愣了一下:"那不是个学术型数据库吗?生产环境能用?"
我说:你大概还停留在十年前的印象里。今天这篇,我就带你从零开始,把 PostgreSQL 装到生产环境上,调好安全配置,再优化到能扛高并发。看完你自然就明白,为什么现在越来越多大厂把核心业务从 MySQL 切到 PG。
一、PostgreSQL 是什么?为什么值得用?
PostgreSQL(简称 PG)是一个开源的对象关系型数据库,诞生于 1986 年的加州大学伯克利分校,到现在已经活了将近 40 年。它是目前功能最强大、最接近 SQL 标准的开源数据库。
很多人拿它和 MySQL 比,简单说几句核心区别:
• ACID 事务支持更强:PG 的 MVCC(多版本并发控制)实现得非常干净,高并发场景下不会出现 MySQL 那种"幻读"问题
• 数据类型更丰富:原生支持 JSONB、数组、几何、IP 地址、UUID 等类型,不用像 MySQL 那样用 varchar 硬凑
• 扩展性强:PostGIS(地理信息)、pgvector(向量搜索)、TimescaleDB(时序数据)—— 这些都是 PG 生态的杀手级插件
• 复杂查询能力强:窗口函数、CTE(WITH 语句)、递归查询,写复杂报表的时候 PG 能让你少掉很多头发
说白了,MySQL 适合"够用就行"的场景,PostgreSQL 适合"我要把这件事做到极致"的场景。
二、方式一:二进制安装(推荐生产环境)
二进制安装是最快的方式,直接用包管理器装,几分钟搞定。适合绝大多数生产场景。下面分别给出 RHEL 系和 Debian 系的安装方法。
2.1 RHEL / CentOS / Rocky / AlmaLinux
先添加 PostgreSQL 官方 YUM 仓库,再安装最新版本(以 PG 17 为例):
# 安装官方 YUM 仓库
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 禁用系统自带的 postgresql 模块
sudo dnf -qy module disable postgresql
# 安装 PostgreSQL 17 服务端
sudo dnf install -y postgresql17-server
# 初始化数据库
sudo /usr/pgsql-17/bin/postgresql-17-setup --initdb
# 设置开机自启并启动服务
sudo systemctl enable postgresql-17
sudo systemctl start postgresql-17
安装完成后验证:
# 查看版本
psql --version
# 输出: psql (PostgreSQL) 17.4
2.2 Ubuntu / Debian
Debian 系更简单,官方仓库直接装:
# 导入官方仓库签名密钥
sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
# 安装 PostgreSQL 17
sudo apt install -y postgresql-17
# 服务会自动启动,验证一下
sudo systemctl status postgresql
Ubuntu/Debian 的好处是安装后服务已经自动启动并设为开机自启,不需要额外的初始化步骤。这一点比 RHEL 系省心不少。
三、方式二:源码编译安装(适合深度定制)
什么时候需要从源码编译?三种场景:一是官方仓库没有你需要的版本;二是你要开启某些编译时选项(比如 DTrace 支持、特定文件系统支持);三是你想把 PG 装到自定义路径,不影响系统已有的包。
3.1 安装编译依赖
RHEL 系:
sudo yum groupinstall -y "Development Tools"
sudo yum install -y zlib-devel readline-devel libicu-devel openssl-devel
Debian 系:
sudo apt install -y gcc build-essential zlib1g-dev libreadline-dev libicu-dev libssl-dev pkg-config
3.2 下载、编译、安装
# 下载源码包
wget https://ftp.postgresql.org/pub/source/v17.4/postgresql-17.4.tar.bz2
# 解压
tar -xvf postgresql-17.4.tar.bz2
cd postgresql-17.4
# 配置(指定安装路径)
./configure --prefix=/usr/local/pgsql
# 编译(用 -j 加速,多核并行)
make -j $(nproc)
# 安装
sudo make install
3.3 编译 contrib 扩展(推荐)
contrib 目录里有很多实用扩展,比如 pg_stat_statements(慢查询分析)、uuid-ossp、hstore 等。建议一起编译:
cd contrib
make -j$(nproc)
sudo make install
3.4 配置环境变量
编译安装完成后,需要把 PG 的二进制路径加到 PATH 里:
echo 'export PATH=/usr/local/pgsql/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
四、PostgreSQL 初始化与安全配置
不管是二进制安装还是源码安装,装好之后还有几件必须要做的事。这一步做不好,你的数据库就是裸奔状态,上线就是安全隐患。
4.1 创建 postgres 系统用户
PG 要求用一个专用的系统用户来运行数据库服务,默认叫 postgres。如果用 root 运行,PG 会直接拒绝启动。二进制安装时这个用户已经自动创建了,但源码安装需要你手动创建:
sudo useradd -m -s /bin/bash postgres
4.2 初始化数据库集群
切换到 postgres 用户,用 initdb 初始化数据目录:
sudo mkdir -p /pgdata/data
sudo chown -R postgres:postgres /pgdata
sudo chmod 700 /pgdata/data
su - postgres
initdb -D /pgdata/data -U postgres -W
参数说明:-D 指定数据目录,-U 指定超级用户,-W 会在初始化时提示你设置密码。
4.3 启动服务
# 源码安装用 pg_ctl 启动
pg_ctl -D /pgdata/data -l /pgdata/logfile start
# 二进制安装(RHEL)用 systemctl
sudo systemctl start postgresql-17
4.4 安全配置(CRITICAL)
这一步非常关键,很多人就是漏了它导致数据库被攻击。PostgreSQL 有两个核心配置文件:
• postgresql.conf:数据库主配置文件,控制监听地址、端口、连接数等
• pg_hba.conf:主机认证配置文件,控制谁能连接、用什么方式认证
4.4.1 修改监听地址
默认 PG 只监听 localhost,外部连不上。如果需要远程连接:
# 编辑配置文件
vi /pgdata/data/postgresql.conf
# 修改这一行:
listen_addresses = '*'
# 或者指定具体 IP:
listen_addresses = '192.168.1.100'
4.4.2 配置 pg_hba.conf 访问控制
这是安全配置的核心!pg_hba.conf 控制哪些主机可以连接、用什么认证方式。默认配置通常比较宽松,生产环境必须收紧:
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all md5
host all all 192.168.1.0/24 md5
host all all 10.0.0.0/8 md5
# 禁止其他所有远程连接
host all all 0.0.0.0/0 reject
解释一下:
• peer:本地通过系统用户认证,只有系统用户 postgres 能以 postgres 身份登录
• md5:密码认证,远程连接必须提供密码
• reject:拒绝所有不在允许范围内的 IP
4.4.3 修改 postgres 用户密码
初始化后第一步,给超级用户设置强密码:
su - postgres
psql -c "ALTER USER postgres WITH PASSWORD '你的强密码';"
4.4.4 重启生效
# 修改配置后需要重启
sudo systemctl restart postgresql-17
# 或者
pg_ctl -D /pgdata/data restart
五、高并发性能优化
默认配置下的 PostgreSQL 能跑,但性能很差。就像一辆跑车出厂时默认用经济模式,你不调参数,根本跑不出它的实力。下面以一台 16 核、32GB 内存的生产服务器为例,讲讲最关键的调优参数。
5.1 内存相关参数
shared_buffers(共享缓冲区)
这是 PG 最重要的内存参数,控制数据库用来缓存数据页的内存大小。默认值只有 128MB,对于生产环境来说太小了。建议设为物理内存的 25%-40%:
shared_buffers = 8GB
# 32GB内存的服务器,设为8GB(25%)
注意:这个参数改了之后需要重启数据库才能生效。
work_mem(工作内存)
每个查询操作(排序、哈希、聚合等)可以使用的内存。默认 4MB 太小,复杂查询会 spill 到磁盘。建议:
work_mem = 16MB
# OLTP场景4MB-16MB,OLAP场景可以更大
注意:work_mem 是按操作分配的,一个复杂查询可能有多个排序操作。设太大容易导致内存耗尽。计算公式参考:work_mem = (总内存 - shared_buffers) / max_connections / 4
effective_cache_size(有效缓存大小)
这个参数不实际分配内存,而是告诉查询优化器"操作系统大概有多少缓存可用"。值越大,优化器越倾向于走索引扫描。建议设为物理内存的 50%-75%:
effective_cache_size = 24GB
# 32GB内存,设为75%
maintenance_work_mem(维护工作内存)
用于 VACUUM、CREATE INDEX 等维护操作的内存。设大一些可以加快这些操作:
maintenance_work_mem = 512MB
5.2 连接数与WAL优化
max_connections(最大连接数)
默认 100,高并发场景远远不够。但也不是越大越好,每个连接都会消耗内存:
max_connections = 500
# 超过500建议用连接池(PgBouncer)
wal_buffers(WAL 日志缓冲区)
高写入场景下建议手动设置:
wal_buffers = 16MB
checkpoint 参数(PG 15+)
检查点会把内存中的脏页写入磁盘,频率太高会产生大量 IO。PG 15+ 用 max_wal_size 替代了老的 checkpoint_segments:
max_wal_size = 2GB
min_wal_size = 512MB
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
checkpoint_completion_target = 0.9 表示检查点的写入分散在 90% 的时间内完成,避免瞬时 IO 峰值。
5.3 完整优化配置清单
把下面的配置加到 postgresql.conf 末尾,重启即可生效:
# === 内存配置 ===
shared_buffers = 8GB
work_mem = 16MB
effective_cache_size = 24GB
maintenance_work_mem = 512MB
# === 连接配置 ===
max_connections = 500
# === WAL配置 ===
wal_buffers = 16MB
max_wal_size = 2GB
min_wal_size = 512MB
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
# === SSD优化 ===
random_page_cost = 1.1
effective_io_concurrency = 200
# === 慢查询日志 ===
log_min_duration_statement = 500
# === 自动清理 ===
autovacuum = on
autovacuum_vacuum_cost_delay = 20ms
5.4 优化效果验证
调优完成后,可以用 PG 自带的 pgbench 做压力测试:
# 初始化测试数据(100倍缩放,约1500万行)
pgbench -i -s 100 postgres
# 500并发,跑60秒
pgbench -c 500 -j 16 -T 60 postgres
在 16 核/32GB 环境下,默认配置的 TPS 大概在 800-900 左右,优化后可以达到 4000+,差距非常明显。你还可以通过缓存命中率来验证优化效果:
SELECT sum(blks_hit) / (sum(blks_hit) + sum(blks_read)) AS cache_hit_ratio FROM pg_stat_database;
优化前缓存命中率可能在 89% 左右,优化后应该达到 99% 以上。
总结一下
这篇我们走完了 PostgreSQL 从安装到生产调优的完整流程:
• 二进制安装适合 90% 的场景,简单快捷
• 源码编译适合需要深度定制的高级玩家
• 安全配置不能偷懒,pg_hba.conf 是最后一道防线
• 默认参数只够"能跑",shared_buffers、work_mem、max_connections 这三个参数调对了,性能提升 5 倍以上
数据库这东西,装上是第一步,调好才是真本事。
夜雨聆风