ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Linux下PostgreSQL安装部署与调优实战指南

Linux下PostgreSQL安装部署与调优实战指南 从零开始在Linux上把PostgreSQL跑起来这件事看起来简单真正动手的时候坑不少。我这几年在CentOS、Ubuntu、麒麟V10这些系统上都部署过也帮同事处理过各种疑难杂症今天把完整的安装部署过程、配置调优思路和排查经验一次性写清楚。这篇内容适合刚接触PostgreSQL的运维和开发同学也适合准备把自己手头MySQL业务迁移过来的团队参考从环境准备到安全加固都有照着做基本能少走一半弯路。1. 安装前的环境规划与版本选型1.1 先想清楚你要装哪个版本很多人在第一步就栽了跟头直接apt install postgresql或者yum install postgresql装出来一个老掉牙的版本后面做分区、JSONB查询、增量同步的时候才发现功能对不上又得折腾升级。PostgreSQL的版本策略和MySQL不太一样它每年出一个大版本每个大版本维护5年。我的建议很简单新项目直接上当前最新的稳定大版本目前16和17都是不错的选择15也还在维护期内如果是替换现有业务尽量选择和源业务小版本差距不超过两个大版本的目标比如从12升到15或16迁移成本可控千万不要在生产环境用测试版或者刚发布不到半年的beta版本有些扩展插件还没来得及适配。那怎么确认你系统源里的版本CentOS系可以执行yum info postgresql-serverUbuntu系执行apt-cache policy postgresql先把版本号看清楚再决定。如果源里版本太老就考虑用PostgreSQL官方提供的Yum/Apt源后面会详细说。1.2 系统与硬件层面要准备什么PostgreSQL本身对硬件要求不算苛刻2核4GB的云主机跑个小中型业务完全没问题但有几个点值得提前确认磁盘空间数据目录至少预留实际数据量的1.5到2倍空间WAL日志、临时文件、索引重建都需要额外空间我见过太多因为磁盘写满导致数据库直接宕机的案例文件系统ext4和xfs都用过个人更倾向xfs尤其在高并发写入场景下表现更稳而且后续做快照备份也方便swap如果内存紧张swap别设成0建议设置为物理内存的0.5到1倍避免内存抖动时OOM直接杀掉数据库进程文件句柄数默认的1024连接数上限很容易被连接池打满建议在/etc/security/limits.conf里把postgres用户的nofile调高到65535。此外要注意关闭系统的透明大页THP这个对数据库性能有明显影响。PostgreSQL官方文档里也提到过透明大页在高并发下会增加延迟波动。临时关闭方式echo never /sys/kernel/mm/transparent_hugepage/enabled永久生效就把这个配置写入/etc/rc.local或者对应的内核参数配置文件中。1.3 配置好主机名和字符集安装前先把系统的主机名和/etc/hosts配好否则后面做流复制或者主从切换时会因为主机名解析出各种莫名其妙的问题。字符集推荐默认使用UTF8同时把locale也统一成en_US.UTF-8或C.UTF-8避免出现中文乱码和排序异常。hostnamectl set-hostname pg01 echo 192.168.1.10 pg01 /etc/hosts localectl set-locale LANGen_US.UTF-8这里有个小细节如果你已经在系统里初始化过数据库再改hostname和locale是不会有任何影响的所以这些操作一定要放在initdb之前做完。2. 三种安装方式对比与选型建议2.1 包管理器安装最省心适合大多数人用系统自带的包管理器安装PostgreSQL是最快的路径。CentOS/RHEL系列# 先安装EPEL源CentOS 7/8 yum install -y epel-release # 安装PostgreSQL yum install -y postgresql-server postgresql-contribUbuntu/Debian系列apt update apt install -y postgresql postgresql-contrib优点是速度快、和系统集成度好、卸载干净缺点是版本可能偏旧比如Ubuntu 20.04自带的还是PostgreSQL 12。对于想尝鲜新特性的场景我会用官方源替换默认源。以CentOS 7上安装PostgreSQL 15为例# 安装官方仓库RPM包 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm # 禁用系统自带的pgdg源如果之前装过 yum -y install postgresql15-server postgresql15-contribUbuntu 22.04安装PostgreSQL 16# 导入官方GPG密钥 curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/pgdg.gpg # 配置源 echo deb [signed-by/usr/share/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt jammy-pgdg main /etc/apt/sources.list.d/pgdg.list apt update apt install -y postgresql-162.2 源码编译安装适合定制化场景如果需要对PostgreSQL做定制编译比如修改某些编译参数、打补丁、或者安装到非标准路径源码编译是绕不开的。编译过程本身不复杂主要耗时在依赖安装和编译等待上# 安装编译依赖 yum install -y gcc gcc-c readline-devel zlib-devel perl-devel python3-devel # 下载源码 wget https://ftp.postgresql.org/pub/source/v16.1/postgresql-16.1.tar.gz tar -zxvf postgresql-16.1.tar.gz cd postgresql-16.1 # 配置编译选项 ./configure --prefix/usr/local/pgsql --with-python --with-perl --with-libxml --with-openssl # 编译并安装-j参数可以加速 make -j4 make install需要注意源码安装后默认不会创建postgres系统用户也不会初始化数据目录这些都要手动操作适合对Linux操作比较熟练的同学。2.3 Docker方式部署隔离环境的好选择如果是本地开发环境或者微服务架构Docker部署PostgreSQL非常方便docker run -d \ --name postgres16 \ -e POSTGRES_USERadmin \ -e POSTGRES_PASSWORDyourpassword \ -e POSTGRES_DBappdb \ -p 5432:5432 \ -v /data/postgres:/var/lib/postgresql/data \ postgres:16但生产环境如果要跑在Docker里有几个问题必须提前考虑清楚数据卷的IO性能、容器重启后的数据安全、以及网络模式的选择。个人建议生产库还是直接跑在物理机或者VM上Docker更适合测试和CI/CD场景。2.4 国产系统上的特殊处理最近在麒麟V10和统信UOS上部署PostgreSQL的需求越来越多这两类系统的源里默认带的版本通常比较老而且epel-release这些第三方源不一定兼容。我的建议是优先使用官方源码编译方式避免依赖问题或者从PostgreSQL官方Yum源里手动下载对应RPM包用rpm -ivh安装注意依赖包要一起装上国产系统如果基于CentOS 8或 openEuler可以尝试直接用系统的dnf源安装部分发行版已经直接收录了PostgreSQL。3. 数据库初始化与核心配置详解3.1 初始化数据库到底做了什么安装完成后第一件事是初始化数据目录。不同安装方式的初始化命令略有区别包管理器安装CentOS# 注意CentOS上如果安装的是postgresql15-server命令格式略有不同 /usr/pgsql-15/bin/postgresql-15-setup initdbUbuntu安装的版本一般会自动完成初始化无需手动操作。如果是源码安装需要手动创建用户和目录useradd postgres mkdir -p /usr/local/pgsql/data chown postgres:postgres /usr/local/pgsql/data su - postgres /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/datainitdb做的事情包括创建数据目录结构、生成postgresql.conf和pg_hba.conf配置模板、创建默认数据库postgres和模板库、设置超级用户权限。默认的超级用户是postgres不是root这一点和MySQL差异很大很多新手会在这里犯迷糊。3.2 postgresql.conf参数调优照着抄就行postgresql.conf是PostgreSQL的核心配置文件里面参数非常多但真正需要手动调整的核心参数其实就几个。以一台4核8GB内存的机器为例子我一般这样设置# 连接相关 listen_addresses 0.0.0.0 # 监听所有地址生产环境可以换成具体IP port 5432 max_connections 200 # 别盲目调大每个连接都要消耗内存 # 内存相关8GB内存的推荐值 shared_buffers 2GB # 约为内存的25%用于共享缓存 effective_cache_size 6GB # 约为内存的75%用于查询计划的缓存估算 work_mem 32MB # 单个排序/哈希操作可使用的内存 maintenance_work_mem 256MB # VACUUM、CREATE INDEX等维护操作使用 # WAL相关 wal_level replica # 如果要搭主从必须设置 max_wal_senders 10 # 主从复制用最大WAL发送进程数 checkpoint_timeout 15min max_wal_size 2GB min_wal_size 80MB # 日志相关 logging_collector on log_directory log log_filename postgresql-%Y-%m-%d.log log_statement ddl # 只记录DDL语句降低日志量 log_min_duration_statement 1000 # 记录执行超过1秒的慢SQL关于shared_buffers有个常见的误区是以为越大越好其实PostgreSQL还有操作系统层面的缓存shared_buffers设置过高反而会导致内存管理开销增大。经验值一般是物理内存的25%左右超过32GB内存的机器可以适当降低比例。work_mem这个参数特别容易被忽略它在排序、JOIN操作时使用默认4MB在数据量大时会频繁触发临时文件落盘。但也不能一下子调太大因为它是按会话分配的200个连接同时排序每个分配64MB就是12.8GB直接能把内存打爆。建议从32MB开始观察临时文件使用情况再做调整。3.3 pg_hba.conf配置连接认证的门禁pg_hba.conf决定了谁能连数据库、用什么方式认证。默认配置一般只允许本地连接生产环境需要按需开放远程访问。常见的配置写法如下# 类型 数据库 用户 地址 认证方式 local all all trust # 本地socket连接免密仅限本地 host all all 127.0.0.1/32 scram-sha-256 host all all 192.168.1.0/24 scram-sha-256 host all all 0.0.0.0/0 md5 # 不推荐仅测试用强烈不建议在生产环境使用trust认证这意味着任何能连到数据库端口的用户都可以免密登录。scram-sha-256是当前最安全的密码认证方式从PostgreSQL 14起已经是默认值。md5认证方式虽然还存在但已经被标记为过时。配置完pg_hba.conf后需要重载配置生效su - postgres -c psql -c SELECT pg_reload_conf();3.4 使用systemd管理PostgreSQL服务现在的主流Linux发行版都用systemd来管理服务PostgreSQL的包管理器安装会自动注册好服务。常用的管理命令# 启动/停止/重启 systemctl start postgresql-15 systemctl stop postgresql-15 systemctl restart postgresql-15 # 设置开机自启 systemctl enable postgresql-15 # 查看服务状态和日志 systemctl status postgresql-15 journalctl -u postgresql-15 -f这里需要注意Ubuntu和CentOS上的服务名可能不同Ubuntu的一般是postgresqlCentOS上装了哪个版本就是postgresql-15这样的格式。4. 创建用户、数据库与基础权限管理4.1 数据库和用户的对应关系PostgreSQL里的用户角色和数据库是独立的这一点和MySQL有点不一样。MySQL里CREATE DATABASE指定字符集然后GRANT ALL ON db.* TO user就完事了PostgreSQL里你要先创建用户再创建数据库然后把数据库的owner赋给用户。常用操作# 切换到postgres系统用户 su - postgres # 进入psql命令行 psql # 创建用户设置密码 CREATE USER app_user WITH PASSWORD SecurePass123; # 创建数据库并指定owner CREATE DATABASE app_db OWNER app_user ENCODING UTF8; # 查看所有数据库 \l # 查看所有用户 \du # 退出psql \q开发环境想省事用户和数据库同名是比较常见的做法。生产环境建议按应用划分不同的用户和数据库权限最小化。4.2 授权与回收权限的正确姿势PostgreSQL的权限体系和MySQL差别很大初学者容易绕晕。核心理解三点数据库的CONNECT、CREATE、TEMPORARY权限是数据库级别的表、序列、函数等对象的SELECT、INSERT、UPDATE、DELETE权限是对象级别的高权限角色可以通过GRANT把权限往下分发。实际中最常用的授权操作-- 授予用户连接数据库权限 GRANT CONNECT ON DATABASE app_db TO app_user; -- 授予用户在指定schema下创建表的权限 GRANT CREATE ON SCHEMA public TO app_user; -- 授予用户所有表的DML权限 GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user; -- 设置未来新建表的默认权限关键否则新表创建后又要重新授权 ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;最后一行ALTER DEFAULT PRIVILEGES特别实用很多同学只授了当前表的权限结果应用新建一张表后直接报权限错误就是这个没配好。4.3 修改默认超级用户密码刚安装完的PostgreSQL默认有个postgres超级用户但在很多包管理器的默认配置下本地socket连接是trust免密的这意味着任何能登录到Linux服务器的用户都可以轻易进入数据库。生产环境务必执行su - postgres psql -c ALTER USER postgres WITH PASSWORD 一个强密码;同时把pg_hba.conf里的本地连接从trust改成scram-sha-256local all all scram-sha-256改完重载配置。别笑我见过好几台测试服务器被人用默认配置直接日穿数据被删了才来找我恢复。5. 远程连接配置与常见错误处理5.1 开放远程访问的三步操作远程连接连不上90%是这三件事没做全监听地址改为允许外部访问listen_addresses *或具体的IPpg_hba.conf里添加允许的网段云安全组/防火墙放行5432端口很多云服务器默认安全组是不放行数据库端口的。检查防火墙的命令# firewalldCentOS 7 firewall-cmd --permanent --add-port5432/tcp firewall-cmd --reload # 或者直接检查iptables iptables -L -n | grep 5432连不上时先用telnet或者nc测试端口通不通再判断是网络问题还是PostgreSQL配置问题。5.2 三种常见连接报错排查报错一Connection refused端口不通检查顺序数据库进程是否存在systemctl status、端口是否被监听ss -lntp | grep 5432、防火墙是否放行、云安全组是否配置。报错二No pg_hba.conf entry for hostpg_hba.conf里没有匹配到客户端的IP地址。检查客户端的实际IP添加到对应的规则段中。这里有个坑如果客户端经过NAT转发看到的源IP可能是网关地址这时候要在数据库端通过pg_stat_activity查看实际连接的IP。报错三password authentication failed密码错误或者认证方式不对。如果确认密码没错检查pg_hba.conf中对应条目的认证方式是否为scram-sha-256有些老版本数据库默认是md5。5.3 连接数打满了怎么办生产环境最常见的问题之一就是FATAL: sorry, too many clients already。这个错误说明连接数达到了max_connections上限。常见原因和处理思路应用连接池配置过大比如连接池设置了100个连接但数据库max_connections只配了50应用代码频繁创建连接但没有正确关闭数据库里有慢SQL或长事务占着连接不放。排查命令-- 查看当前连接数和使用情况 SELECT state, count(*) FROM pg_stat_activity GROUP BY state; -- 查看具体连接的信息 SELECT pid, usename, application_name, client_addr, backend_start, state FROM pg_stat_activity ORDER BY backend_start; -- 终止不活跃的连接 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state idle AND usename postgres;根本上还是要让应用使用连接池比如PgBouncer、Pgpool-II或者应用框架自带的连接池组件。裸连数据库的方式在高并发下很难撑住。6. 备份恢复与日常运维必备技能6.1 逻辑备份pg_dump和pg_restorepg_dump是PostgreSQL自带的逻辑备份工具适合中小型数据库。基本用法# 备份单个数据库 pg_dump -h 127.0.0.1 -U app_user -F c -f app_db.dump app_db # 恢复数据库需要先创建目标数据库 createdb -U postgres new_db pg_restore -h 127.0.0.1 -U postgres -d new_db app_db.dump-F c表示自定义格式支持选择性恢复比纯SQL格式更灵活。如果要备份所有数据库用pg_dumpallpg_dumpall -U postgres all_backup.sql6.2 物理备份更快的全量备份方案大数据量场景下逻辑备份太慢需要用物理备份。最简单的方法是直接复制数据目录但要求数据库处于停止状态或者使用pg_start_backup进入备份模式。还有一种常用方案是结合barman等专业备份工具支持增量备份和时间点恢复PITR。手动做物理备份的核心步骤# 进入备份模式 su - postgres -c psql -c SELECT pg_start_backup(full_backup); # 同步数据目录到备份位置 rsync -av /var/lib/pgsql/15/data/ /backup/postgres_full/ # 结束备份模式 su - postgres -c psql -c SELECT pg_stop_backup();日常生产环境还是推荐用barman或者pgBackRest这类专业工具支持自动归档WAL、增量备份、自动清理过期备份省心很多。6.3 掌握几个实用的管理SQL日常运维中高频使用的管理操作-- 查看数据库大小 SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database ORDER BY pg_database_size(pg_database.datname) DESC; -- 查看表大小 SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename)) AS size FROM pg_tables WHERE schemaname public ORDER BY pg_total_relation_size(tablename) DESC; -- 查看当前正在执行的查询 SELECT pid, query_start, state, query FROM pg_stat_activity WHERE state active; -- 终止指定PID的查询 SELECT pg_cancel_backend(pid); -- 取消查询 SELECT pg_terminate_backend(pid); -- 终止连接pg_cancel_backend和pg_terminate_backend的区别要注意前者只是取消正在执行的SQL连接还活着后者会直接断开整个连接所有未提交的事务都会回滚。6.4 定时的VACUUM与监控体系PostgreSQL的MVCC机制决定了表中的旧版本数据不会立即清理需要定期执行VACUUM。从9.6版本开始autovacuum默认开启一般情况下不需要手动干预。但在大表频繁UPDATE、DELETE的场景下autovacuum可能跟不上需要关注pg_stat_user_tables中的n_dead_tup字段。-- 查看死元组比例超过20%需要重点关注 SELECT relname, n_live_tup, n_dead_tup, round(n_dead_tup * 100.0 / (n_live_tup n_dead_tup), 2) AS dead_ratio FROM pg_stat_user_tables WHERE n_live_tup 0 ORDER BY dead_ratio DESC;监控方面Prometheus加上postgres_exporter是目前最主流的组合可以采集连接数、事务数、缓存命中率、复制延迟等指标再配合Grafana做可视化告警。部署方式不复杂网上也有现成的Dashboard模板可以导入。7. 安全加固与等保合规实践7.1 最小权限原则落地除了前面说的不要用trust认证之外还要注意应用账号只授予必要的权限不要直接用超级用户postgres跑应用即使在同一内网不同应用也建议使用不同的数据库账号方便审计和追溯定期检查pg_hba.conf中的授权规则清理过期或者过宽的访问条目。查询当前所有角色和权限可以用这条SQLSELECT r.rolname, r.rolsuper, r.rolcreatedb, r.rolcreaterole, r.rolcanlogin, ARRAY(SELECT b.rolname FROM pg_auth_members m JOIN pg_roles b ON m.roleid b.oid WHERE m.member r.oid) AS member_of FROM pg_roles r;7.2 SSL连接加密如果数据库和应用之间要走公网或者半可信网络强烈建议开启SSL。PostgreSQL从安装时就支持SSL配置方式不复杂# 生成自签名证书或者使用企业CA签发的证书 openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key chmod 600 server.key cp server.crt server.key /var/lib/pgsql/15/data/然后修改postgresql.confssl on ssl_cert_file server.crt ssl_key_file server.key重启数据库后在客户端连接时加上sslmoderequire参数即可强制加密连接。7.3 日志审计配置等保和内部审计往往要求记录数据库操作日志。PostgreSQL自带的日志功能虽然不像专业审计工具那么强但基本够用log_connections on log_disconnections on log_statement ddl # 或者 mod 记录DDLDML log_duration off log_line_prefix %t [%p]: [%l-1] user%u,db%d,client%h log_statement设置成all会记录所有SQL日志量会非常大一般不建议在生产环境开启除非是等保测评的短期要求。8. 实操总结从安装到上线的完整命令流最后给一套可以直接抄作业的部署命令流以CentOS 7 PostgreSQL 15为例# 1. 安装官方源 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm # 2. 安装服务 yum install -y postgresql15-server postgresql15-contrib # 3. 初始化数据库 /usr/pgsql-15/bin/postgresql-15-setup initdb # 4. 启动并设置开机自启 systemctl start postgresql-15 systemctl enable postgresql-15 # 5. 修改postgres用户密码 su - postgres -c psql -c \ALTER USER postgres WITH PASSWORD StrongPass2024\ # 6. 修改监听配置 sed -i s/#listen_addresses localhost/listen_addresses 0.0.0.0/ /var/lib/pgsql/15/data/postgresql.conf # 7. 配置pg_hba.conf追加远程访问规则 echo host all all 192.168.1.0/24 scram-sha-256 /var/lib/pgsql/15/data/pg_hba.conf # 8. 重载配置 systemctl reload postgresql-15整套流程跑下来一个可用的PostgreSQL实例就上线了。后面再根据业务特点调整内存参数、创建业务账号和数据库、配置备份策略和监控告警就进入日常运维的轨道了。用Linux部署PostgreSQL这件事看起来就是简单的装包改配置但实际上每一个决定背后都有它的逻辑版本选型决定了后面能用的特性范围初始化参数决定了性能上限认证配置决定了安全边界。按照前面的步骤走一遍配合对每个参数的理解后面出问题的时候你就能有依据地排查而不是靠猜。如果实际操作中遇到上面没覆盖到的问题欢迎留言交流我看到了会抽空回复。
返回列表