CentOS 8 上用 dnf 部署生产级 PostgreSQL 12 实战指南
1. 项目概述:为什么在 CentOS 8 上亲手装 PostgreSQL 是件值得花两小时的事
PostgreSQL、CentOS 8、install、use、dnf——这五个词凑在一起,不是一份运维面试题,而是一线系统工程师每天真实面对的生产环境起点。我做过上百次数据库部署,从物理服务器到云主机,从裸机安装到容器化交付,但每次在全新 CentOS 8 环境里敲下第一条dnf install命令前,我都会停三秒:这不是“照着教程点下一步”的操作,而是为后续半年甚至三年的数据稳定性、权限模型、备份策略、高可用演进埋下第一颗钉子。CentOS 8 已于 2021 年底停止维护,但大量企业内网、测试集群、遗留系统仍在运行它;而 PostgreSQL 作为公认的“最先进开源关系型数据库”,其 JSONB 支持、物化视图、逻辑复制、行级安全策略等能力,远超“能存数据”这个基础需求。你真正需要的,不是“怎么装上”,而是“装成什么样才扛得住业务增长”。比如,直接dnf install postgresql-server装出来的默认实例,监听地址是127.0.0.1,密码认证方式是ident,数据目录在/var/lib/pgsql/data——这三个配置项,90% 的新手会在三天后因为连不上远程客户端、改不了密码、或磁盘爆满而深夜重启服务。这不是故障,是设计缺失。本文不讲“PostgreSQL 和 MySQL 区别”这种泛泛而谈的对比(那属于架构选型阶段),也不教你怎么用 WSL 或 VMware 安装 CentOS 8(那是环境准备环节),而是聚焦一个具体动作:在一台干净的 CentOS 8 系统上,用原生 dnf 工具链,完成一次生产就绪(production-ready)级别的 PostgreSQL 部署与首次使用验证。你会看到每一步背后的取舍——为什么不用yum(它在 CentOS 8 中已被 dnf 完全替代)?为什么必须初始化后再改pg_hba.conf(而不是先改再 init)?为什么postgres用户不能直接登录 shell(这是安全基线强制要求)?所有答案都来自我踩过的坑:某次因跳过postgresql-setup --initdb直接启动服务,导致 WAL 日志无法归档,备份脚本静默失败;另一次因未设置shared_buffers,在 32GB 内存机器上只分配了 128MB,TPS 直接腰斩。这不是理论推演,是血泪换来的 checklist。适合谁?如果你正要给测试环境搭一套数据库、要给开发同事配一个可共享的 PostgreSQL 实例、或是刚接手一台老 CentOS 8 服务器需要快速恢复数据库服务——这篇文章就是你的操作手册。它不假设你懂 SQL,但默认你熟悉 Linux 基础命令(ls,cat,systemctl,sudo)。接下来的内容,每一行命令都有上下文,每一个配置项都有后果说明,每一段解释都对应一个真实场景。我们开始。
2. 整体设计思路与方案选型逻辑:为什么坚持用 dnf + 官方仓库,而不是源码编译或 Docker
2.1 为什么放弃源码编译:省下的时间,最后都花在了补丁上
有人会问:“源码编译不是最可控吗?”——这话对,但只对了一半。我在 2019 年给金融客户部署时试过源码编译 PostgreSQL 11.5,过程看似完美:下载 tarball、./configure --prefix=/opt/pgsql --with-openssl --with-python、make && make install。但问题出在后续:当客户突然要求支持 TimescaleDB(时序扩展)时,我得重新编译整个 PostgreSQL,因为 TimescaleDB 的.so文件必须与 PostgreSQL 主版本、编译参数、甚至 GCC 版本严格匹配。更麻烦的是安全更新——CVE-2022-41896 修复需要升级到 14.6,我得重新走一遍 configure → make → install 流程,还要手动迁移数据目录。而用 dnf 安装,dnf update postgresql-server一条命令搞定,RPM 包管理器自动处理依赖、文件覆盖、服务重载。CentOS 8 的官方 AppStream 仓库中,PostgreSQL 10 是默认流(stream),但通过启用postgresql:12模块,可一键切换到更现代的 12.x 版本(12.17 是 CentOS 8 生命周期内最后一个 LTS 版本)。这个模块化设计,正是 dnf 相比旧版 yum 的核心优势:它把“数据库大版本”当作可插拔组件,而非绑定在系统生命周期上。所以我的选择很明确:用 dnf 启用postgresql:12模块,安装预编译 RPM 包。这既保证了二进制兼容性(Red Hat 签名验证),又保留了版本灵活性(dnf module list postgresql可查所有可用流)。
2.2 为什么不用 Docker:容器不是万能胶布
Docker 部署 PostgreSQL 确实快,“docker run -d --name pg -e POSTGRES_PASSWORD=123 -p 5432:5432 -v /data/pg:/var/lib/postgresql/data postgres:12” 一行解决。但问题在于持久化和可观测性。/data/pg这个挂载点,如果宿主机是 CentOS 8,SELinux 默认策略会阻止容器写入该目录,报错Permission denied——你得加:z标签或临时禁用 SELinux,而这在生产环境是红线。更关键的是日志:Docker 容器的标准输出日志,无法像 systemd journal 那样按时间范围精确检索(journalctl -u postgresql -S "2024-01-01"),也无法与现有监控体系(如 Prometheus + node_exporter)无缝集成。我曾遇到一个案例:某次数据库慢查询激增,Docker 日志里只有LOG: duration: 1245.332 ms,但找不到对应的客户端 IP 和 SQL 文本,因为容器日志没开启log_statement = 'all'且未挂载外部日志卷。而原生安装,日志直接落盘在/var/lib/pgsql/data/log/,配合log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ',一条grep "duration.*1000" /var/lib/pgsql/data/log/postgresql-Mon.log就能定位全部慢 SQL。所以,除非你已有成熟的容器编排平台(K8s + PVC + ConfigMap),否则在单机 CentOS 8 上,原生安装是更透明、更易调试的选择。
2.3 为什么锁定 PostgreSQL 12:平衡新特性与长期支持
CentOS 8 AppStream 提供三个 PostgreSQL 流:10(默认)、12、13。我选12,理由很实际:10太老,缺少GENERATED ALWAYS AS IDENTITY(标准自增列语法),开发写 DDL 时总要妥协;13虽新,但 CentOS 8 对其支持截止于 2024 年 5 月(EUS 结束),而12的维护期延续到 CentOS 8 生命周期终结(2024 年底),且12.17已包含所有关键安全补丁。更重要的是生态兼容性:主流 ORM 如 SQLAlchemy 1.4+、Django 3.2+ 对 PG 12 的 JSONB 操作、分区表继承语法支持最成熟。我测试过13的PROCEDURE存储过程功能,但在客户 Java 应用里,JDBC 驱动需升级到 42.2.23+ 才能正确解析,而他们线上用的是 Spring Boot 2.3.x,驱动版本被锁死。PG 12 则无此顾虑,jdbc:postgresql://localhost:5432/mydb连接串零修改即可工作。所以,这不是技术保守,而是风险控制——用经过大规模验证的版本,把精力留给业务逻辑,而不是驱动兼容性排查。
3. 核心细节解析与实操要点:从系统准备到首次连接的 7 个关键决策点
3.1 系统准备:SELinux 和防火墙不是摆设,是第一道防线
CentOS 8 默认启用 SELinux(enforcing 模式)和 firewalld。很多人第一步就setenforce 0或systemctl stop firewalld,这是危险的捷径。正确的做法是让它们为你工作。首先确认 SELinux 状态:
sestatus # 输出应为:enabled, enforcing, mlsPostgreSQL RPM 包已内置 SELinux 策略,但需确保数据目录有正确上下文。默认安装后,/var/lib/pgsql/data的上下文是system_u:object_r:postgresql_db_t:s0,这是安全的。但如果你计划把数据目录移到/data/pgsql(推荐,避免根分区爆满),必须手动打标签:
mkdir -p /data/pgsql semanage fcontext -a -t postgresql_db_t "/data/pgsql(/.*)?" restorecon -Rv /data/pgsqlsemanage命令将/data/pgsql及其子目录永久标记为 PostgreSQL 数据目录类型,restorecon立即应用该上下文。跳过此步,postgresql-setup --initdb会失败并报错SELinux is preventing /usr/bin/postgres from write access on the directory /data/pgsql。
防火墙同理。不要关 firewalld,而是开放 PostgreSQL 端口:
firewall-cmd --permanent --add-port=5432/tcp firewall-cmd --reload--permanent确保重启后规则仍生效。这里有个细节:5432/tcp是标准端口,但如果你在多实例场景(如主从分离),可能需要开5433、5434,此时用--add-port=5432-5434/tcp批量添加。记住,每一次绕过安全机制的“快速安装”,都在为未来的审计失败埋雷。
3.2 模块启用与包安装:dnf 的模块流(stream)是核心控制点
CentOS 8 的 dnf 模块系统是理解安装逻辑的关键。执行dnf module list postgresql,你会看到类似输出:
| Name | Stream | Profiles | Summary |
|---|---|---|---|
| postgresql | 10 | client, server [d], devel | PostgreSQL server and client modules |
| postgresql | 12 | client, server [d], devel | PostgreSQL server and client modules |
| postgresql | 13 | client, server [d], devel | PostgreSQL server and client modules |
其中[d]表示 default(默认流),即dnf install postgresql-server会装10版本。我们要切到12: |
dnf module enable postgresql:12 dnf install postgresql-server postgresql-contribpostgresql-contrib包含pg_stat_statements(性能分析)、tablefunc(交叉表函数)等实用扩展,生产环境必备。注意:enable不是install,它只是告诉 dnf “下次安装时优先用这个流”,所以必须先enable再install。如果误装了10,可用dnf module reset postgresql重置,再enable新流。这个设计的好处是,你可以同时启用多个流(如postgresql:12和nodejs:14),互不干扰,不像旧版 yum 那样全局锁定版本。
3.3 初始化数据库集群:--initdb 的时机与 --data-dir 的绝对路径陷阱
安装完 RPM 包,服务不会自动启动,因为数据目录为空。必须手动初始化:
postgresql-setup --initdb --unit postgresql这条命令做了三件事:以postgres用户身份创建/var/lib/pgsql/data目录结构、生成postgresql.conf和pg_hba.conf初始文件、设置目录权限(drwx------)。关键点在于--unit postgresql参数——它指定 systemd 服务单元名为postgresql(而非默认的postgresql-12),这样systemctl start postgresql才能生效。如果你跳过此步直接systemctl start postgresql,服务会启动失败,journal 日志显示FATAL: data directory "/var/lib/pgsql/data" has wrong ownership。
更常见的错误是自定义数据目录。假设你想把数据放在/data/pgsql,很多人会写:
# 错误!相对路径会导致 initdb 失败 postgresql-setup --initdb --data-dir data/pgsql--data-dir必须是绝对路径。正确写法:
mkdir -p /data/pgsql chown postgres:postgres /data/pgsql postgresql-setup --initdb --data-dir /data/pgsql --unit postgresqlchown是必须的,因为postgresql-setup以 root 运行,但内部调用initdb时会切换到postgres用户,若目录属主不是postgres,初始化会拒绝写入。这个细节,文档里常被忽略,但却是新手卡住最多的地方。
3.4 配置文件精调:postgresql.conf 的 5 个必改参数与 pg_hba.conf 的信任链设计
初始化后,两个核心配置文件位于/var/lib/pgsql/data/(或你指定的--data-dir):
postgresql.conf:数据库引擎参数pg_hba.conf:客户端连接认证规则
postgresql.conf 必改项(用vim编辑):
listen_addresses = 'localhost'→ 改为listen_addresses = 'localhost,127.0.0.1'(显式列出,避免歧义)port = 5432→ 保持默认,除非端口冲突max_connections = 100→ 根据内存调整:公式max_connections ≈ (RAM_in_GB * 1000) / 10,32GB 机器可设300shared_buffers = 128MB→必须改!推荐值为物理内存的 25%,32GB 机器设8GB(shared_buffers = 8GB)logging_collector = on→ 开启日志收集(默认 off)
提示:
shared_buffers是 PostgreSQL 自己管理的内存池,用于缓存数据页。设太小(如默认 128MB)会导致频繁读盘;设太大(如 16GB)会挤占操作系统缓存,反而降低性能。8GB 是 32GB 机器的黄金平衡点,经 pgbench 压测验证。
pg_hba.conf 认证规则(重点!):
默认内容末尾有:
# TYPE DATABASE USER ADDRESS METHOD local all all peer host all all 127.0.0.1/32 ident host all all ::1/128 identpeer表示本地 Unix socket 连接时,用操作系统用户名认证(psql -U postgres无需密码);ident表示 TCP 连接时,用客户端 IP 反向 DNS 查找用户名,这在大多数网络中不可靠。必须改为:
# TYPE DATABASE USER ADDRESS METHOD local all all peer host all all 127.0.0.1/32 md5 host all all ::1/128 md5md5表示密码认证,这是唯一安全的远程连接方式。改完保存,必须 reload 配置:systemctl reload postgresql(不是 restart,避免中断连接)。
3.5 服务管理与开机自启:systemctl 的 reload vs restart 语义差异
PostgreSQL 服务由 systemd 管理,单元文件为/usr/lib/systemd/system/postgresql.service。常用命令:
systemctl start postgresql:启动服务(首次需先--initdb)systemctl enable postgresql:设置开机自启(写入/etc/systemd/system/multi-user.target.wants/postgresql.service符号链接)systemctl status postgresql:查看状态(重点关注Active: active (running)和Loaded: loaded)systemctl reload postgresql:仅重载配置文件(postgresql.conf和pg_hba.conf),不中断现有连接systemctl restart postgresql:完全重启,断开所有客户端连接
注意:
reload不会重新读取postgresql.auto.conf(动态参数文件),它只处理主配置文件。如果用ALTER SYSTEM SET修改了参数,reload无效,必须restart。但restart在生产环境是高危操作,所以日常调优优先用reload,只在必要时restart。
3.6 创建首个用户与数据库:超越postgres超级用户的最小权限实践
postgres用户是安装时自动创建的超级用户(superuser),但它不应被应用直接使用。最佳实践是创建专用用户:
# 切换到 postgres 用户(安全要求:禁止 root 直接运行 psql) sudo -i -u postgres # 进入 psql 命令行 psql # 创建新用户(带密码) CREATE USER myapp WITH PASSWORD 'StrongPass123!'; # 创建数据库,并指定属主 CREATE DATABASE myappdb OWNER myapp; # 退出 psql \q # 退出 postgres 用户 shell exit关键点:CREATE USER必须在psql会话中执行,不能用createdb或createuser命令(它们是 shell 工具,功能有限)。WITH PASSWORD是强制的,否则用户无密码无法登录。OWNER myapp确保该用户对数据库有完全控制权,无需GRANT权限。此时,应用连接字符串为:postgresql://myapp:StrongPass123!@localhost:5432/myappdb
这比用postgres用户安全得多——即使密码泄露,攻击者也只能访问myappdb,无法删库或看其他数据库。
3.7 首次连接验证:psql 的 -U、-d、-h 参数组合与错误诊断树
安装完成后,必须验证连接。在非postgres用户下执行:
psql -U myapp -d myappdb -h localhost参数含义:-U指定用户名,-d指定数据库名,-h指定主机(localhost强制走 TCP,而非 Unix socket)。如果成功,会进入myappdb=>提示符。如果失败,按以下树状图排查:
- 错误:psql: error: could not connect to server: Connection refused
→ 检查服务是否运行:systemctl status postgresql,若inactive,则start - 错误:psql: error: FATAL: password authentication failed for user "myapp"
→ 检查pg_hba.conf是否为md5,且reload了服务;检查密码是否输错(区分大小写) - 错误:psql: error: FATAL: database "myappdb" does not exist
→ 检查数据库是否创建成功:sudo -u postgres psql -c "\l"(\l列出所有数据库) - 错误:psql: error: could not connect to server: No such file or directory
→-h参数缺失,psql 默认走 Unix socket,但 socket 文件路径可能不对;加-h localhost强制 TCP
这个诊断树,是我帮客户远程支持时,90% 连接问题的解决路径。记住,每个错误信息都精准指向一个配置环节,不必猜,按顺序查。
4. 实操过程与核心环节实现:从零到可运行的完整步骤记录(含参数计算与现场输出)
4.1 环境确认与基础准备(耗时 2 分钟)
登录 CentOS 8 系统,确认版本和网络:
# 查看系统版本(确保是 CentOS 8) cat /etc/redhat-release # 输出:CentOS Linux release 8.5.2111 # 确认网络连通性(ping 自己,排除网络配置问题) ping -c 3 localhost # 更新系统(可选,但推荐,确保 dnf 最新) dnf update -y此时,dnf update会拉取元数据,耗时取决于镜像源速度。如果公司内网有 dnf 私服(dnf私服),可配置/etc/yum.repos.d/CentOS-Base.repo指向内网地址,加速安装。但公网环境,直接用默认阿里云或清华源即可,无需折腾。
4.2 启用 PostgreSQL 12 模块并安装(耗时 3 分钟)
执行模块启用和安装:
# 列出可用模块流 dnf module list postgresql # 启用 12 流 dnf module enable postgresql:12 # 安装服务端和扩展包 dnf install -y postgresql-server postgresql-contrib # 验证安装(检查包是否在系统中) rpm -qa | grep postgresql # 输出应包含:postgresql-server-12.17-1.el8_5.x86_64安装过程会自动创建postgres系统用户和组(UID/GID 26),并生成/usr/pgsql-12/目录存放二进制文件。-y参数自动确认,避免交互。
4.3 初始化数据库集群(耗时 1 分钟)
# 创建自定义数据目录(推荐,避免 /var/lib 爆满) mkdir -p /data/pgsql chown postgres:postgres /data/pgsql # 初始化(关键:绝对路径 + --unit) postgresql-setup --initdb --data-dir /data/pgsql --unit postgresql # 检查数据目录权限 ls -ld /data/pgsql # 输出应为:drwx------. 19 postgres postgres 4096 ...初始化成功后,/data/pgsql下会有base/、global/、pg_hba.conf等目录和文件。此时systemctl status postgresql仍显示inactive,因为服务尚未启动。
4.4 配置文件深度修改(耗时 5 分钟)
编辑postgresql.conf:
sudo -u postgres vim /data/pgsql/postgresql.conf找到并修改以下行(用/搜索):
#listen_addresses = 'localhost'→listen_addresses = 'localhost,127.0.0.1'#port = 5432→ 保持原样(取消注释即可)#max_connections = 100→max_connections = 300(按 32GB 内存计算)#shared_buffers = 128MB→shared_buffers = 8GB#logging_collector = off→logging_collector = on
编辑pg_hba.conf:
sudo -u postgres vim /data/pgsql/pg_hba.conf在文件末尾,将ident行改为md5:
host all all 127.0.0.1/32 md5 host all all ::1/128 md54.5 启动服务并设置开机自启(耗时 1 分钟)
# 启动服务 systemctl start postgresql # 设置开机自启 systemctl enable postgresql # 检查状态(关键:Active 应为 running) systemctl status postgresql # 输出片段: # ● postgresql.service - PostgreSQL database server # Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor preset: disabled) # Active: active (running) since Mon 2024-01-01 10:00:00 CST; 5s ago如果Active不是running,立即journalctl -u postgresql -n 50查看最后 50 行日志,定位错误。
4.6 创建应用用户与数据库(耗时 2 分钟)
# 切换到 postgres 用户 sudo -i -u postgres # 进入 psql psql # 执行 SQL(复制粘贴,注意分号) CREATE USER myapp WITH PASSWORD 'MyAppPass2024!'; CREATE DATABASE myappdb OWNER myapp; # 验证创建结果 \l # 列出数据库 \du # 列出用户 # 退出 psql 和 shell \q exit\l输出中应看到myappdb,\du中应看到myapp用户,且Superuser列为no。
4.7 首次连接与基础操作验证(耗时 1 分钟)
# 用新用户连接(-h localhost 强制 TCP) psql -U myapp -d myappdb -h localhost # 在 psql 中创建测试表并插入数据 myappdb=> CREATE TABLE test (id SERIAL PRIMARY KEY, name VARCHAR(50)); myappdb=> INSERT INTO test (name) VALUES ('Hello PostgreSQL'); myappdb=> SELECT * FROM test; # 输出: # id | name # ----+------------- # 1 | Hello PostgreSQL # 退出 myappdb=> \q连接成功、建表成功、查数成功——三个里程碑达成,证明安装完全可用。
5. 常见问题与排查技巧实录:12 个真实故障场景与独家避坑指南
5.1 “Failed to initialize cluster. See /var/lib/pgsql/initdb_postgresql.log” —— 初始化日志是真相之源
这是初始化失败最常见的错误。不要只看终端提示,直接查日志:
cat /var/lib/pgsql/initdb_postgresql.log常见原因及解法:
FATAL: could not create lock file "/var/run/postgresql/.s.PGSQL.5432.lock": Permission denied
→ SELinux 阻止。执行sestatus确认 enforcing,然后setsebool -P postgresql_can_network_connect on允许网络连接。FATAL: data directory "/data/pgsql" has wrong ownership
→chown postgres:postgres /data/pgsql后重试。FATAL: could not create shared memory segment: Cannot allocate memory
→sysctl -w kernel.shmmax=8589934592(8GB),并写入/etc/sysctl.conf永久生效。
实操心得:永远先看
initdb_postgresql.log,它比终端输出详细 10 倍。我曾因一个空格导致--data-dir路径错误,日志里明确写了invalid argument,而终端只报failed。
5.2 “psql: error: could not connect to server: Connection refused” —— 服务状态的三重验证法
当systemctl status postgresql显示active (running),但psql仍连不上,按顺序验证:
- 端口监听:
ss -tlnp | grep 5432,应看到postgres进程监听127.0.0.1:5432。若无输出,服务未真启动。 - 进程存在:
ps aux | grep postgres,应有postgres: logger、postgres: checkpointer等多个进程。若只有logger,主进程崩溃。 - 配置加载:
sudo -u postgres /usr/pgsql-12/bin/pg_ctl -D /data/pgsql status,直接调用 pg_ctl 检查数据目录状态。
注意:
pg_ctl status比systemctl status更底层,能发现 systemd 单元文件配置错误(如Environment=PGDATA指向错误路径)导致的假启动。
5.3 “FATAL: no pg_hba.conf entry for host "192.168.1.100", user "myapp", database "myappdb", SSL off” —— pg_hba.conf 的匹配优先级陷阱
这个错误表明客户端 IP 不在pg_hba.conf规则中。但很多人加了host all all 0.0.0.0/0 md5还是失败,原因是规则匹配是自上而下,第一条匹配即生效。默认规则中,local和host的127.0.0.1/32在顶部,如果你在底部加了0.0.0.0/0,但上面有一条host all all 192.168.1.0/24 reject,那么192.168.1.100会被 reject。解决方案:
- 把允许规则加在
pg_hba.conf文件最上方(在# TYPE DATABASE USER ADDRESS METHOD注释行之后) - 或用
hostssl强制 SSL 连接(更安全):hostssl all all 0.0.0.0/0 scram-sha-256
5.4 “ERROR: column "xxx" of relation "yyy" does not exist” —— 大小写敏感与双引号的隐式转换
PostgreSQL 默认将未加引号的标识符转为小写。如果建表时用了CREATE TABLE "User" ("Name" VARCHAR(50))(带双引号),那么查询必须写SELECT "Name" FROM "User"。新手常犯错误:SELECT Name FROM User,报错column "name" does not exist。这是因为Name被转成小写name,而实际列名是大写Name。避坑口诀:建表不用双引号,查询就不用双引号;一旦用了双引号,永远用双引号。
5.5 “WARNING: there is already a transaction in progress” —— psql 中事务的自动提交陷阱
在psql中,BEGIN后必须COMMIT或ROLLBACK,否则后续命令会报此警告。但更隐蔽的是:psql默认autocommit关闭,所以CREATE TABLE这种 DDL 语句也会开启隐式事务。解决方案:
- 临时开启自动提交:
\set AUTOCOMMIT on - 或始终显式写
BEGIN; ... COMMIT; - 生产脚本中,务必在开头加
BEGIN;,结尾加COMMIT;,避免部分执行。
5.6 “Out of memory: Kill process 12345 (postgres) score 800 or sacrifice child” —— shared_buffers 与 OOM Killer 的生死线
当shared_buffers设得过大(如 16GB),而系统总内存 32GB,Linux OOM Killer 可能杀死postgres进程。dmesg -T | grep -i "killed process"可查日志。安全公式:shared_buffers ≤ (Total_RAM * 0.25),且effective_cache_size = Total_RAM * 0.5。例如 32GB 机器:shared_buffers = 8GB,effective_cache_size = 16GB。后者告诉查询规划器“可用缓存有多大”,影响执行计划选择。
5.7 “pg_dump: error: connection to database "myappdb" failed: FATAL: password authentication failed for user "myapp"” —— 备份脚本的密码传递安全
pg_dump连接失败,常因密码未传入。错误做法:pg_dump -U myapp -W myappdb > backup.sql(-W交互式输入,无法用于脚本)。正确做法:
- 创建
~/.pgpass文件(postgres用户家目录):localhost:5432:myappdb:myapp:MyAppPass2024! - 设置权限:
chmod 600 ~/.pgpass - 脚本中直接调用:
pg_dump -U myapp myappdb > backup.sql.pgpass文件格式:hostname:port:database:username:password,一行一记录,*可通配。
5.8 “ERROR: permission denied for schema public” —— 新用户缺默认 schema 权限
创建用户后,myapp用户能连库,但CREATE TABLE报此错。原因是publicschema 的USAGE和CREATE权限未授予。解决:
-- 以 postgres 用户登录后执行 GRANT USAGE ON SCHEMA public TO myapp; GRANT CREATE ON SCHEMA public TO myapp;或者,在创建用户时,用ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO myapp;设置默认权限。
5.9 “Connection timed out. Is the server running on host "xxx" and accepting TCP/IP connections on port 5432?” —— 防火墙与云厂商安全组的双重检查
本地ping通,但远程psql