资讯动态

CentOS 7下PostgreSQL读写分离实战:pgbouncer+应用路由方案

发布时间:2026/10/15 13:43:53 来源:尧图企业网站定制
1. 项目概述为什么在 CentOS 7 上认真做 Postgres 读写分离不是“可选项”而是“必选项”Postgres 读写分离与配置Centos7——这十个字背后藏着大量中小型业务系统在真实生产环境中反复踩坑、深夜救火后才换来的共识。我接触过至少17个部署在 CentOS 7 环境下的 Postgres 应用从某高校教务系统后台到某电商 SaaS 的订单分析模块再到某物联网平台的设备状态聚合服务它们共有的一个特征是初期单库扛得住半年后查询变慢、报表卡顿、API 响应超时开始集中爆发DBA 查日志第一反应就是“查查有没有没加索引的慢查询”结果发现——90% 的压力根本不是来自 SQL 写法而是读流量把主库 CPU 和 I/O 吃满了。你可能觉得“Postgres 不是自带流复制吗搭个 standby 就完事”但现实远比这复杂。CentOS 7 的 systemd 服务管理机制、SELinux 默认策略、firewalld 的端口白名单逻辑、PostgreSQL 10 版本对pg_hba.conf认证链路的增强校验、甚至recovery.conf在 12 版本后被彻底废弃并整合进postgresql.conf——这些都不是文档里一句“按步骤操作”就能绕过去的。我亲眼见过一个团队花三天时间反复重启postgresql服务失败最后发现只是因为pg_hba.conf中一条hostssl规则写在了host规则之后而 PostgreSQL 的匹配顺序是自上而下导致 SSL 连接请求被前面的非 SSL 规则拦截并拒绝日志里只显示模糊的connection rejected根本不会提示“SSL required but not provided”。更关键的是“读写分离”四个字本身就有误导性。它不是简单地把 SELECT 语句发给从库、INSERT/UPDATE/DELETE 发给主库就万事大吉。Postgres 的强一致性模型决定了从库永远比主库滞后哪怕只有几毫秒这个“滞后窗口”就是业务逻辑的雷区。比如用户刚提交订单前端跳转到“订单详情页”如果这个页面的查询路由到了从库而此时 WAL 日志还没来得及重放页面就会显示“订单不存在”。这不是数据库故障而是架构设计缺失导致的业务逻辑断裂。所以真正的读写分离必须配套一套明确的读策略分级机制哪些读可以容忍延迟如历史数据统计、后台报表哪些读必须强一致如用户中心信息、支付状态核验哪些读需要自动降级回主库如首次查询未命中从库缓存时的兜底逻辑。这套机制在 CentOS 7 环境下落地意味着你要同时搞定三件事底层数据库的高可用复制链路稳定可靠中间层的流量分发策略清晰可控上层应用的连接行为可感知、可干预。它不依赖某个商业中间件也不需要改写整个 ORM 层而是用最朴素的 Linux 工具链 PostgreSQL 原生命令 一份经得起推敲的配置清单把事情做扎实。接下来的内容就是我过去三年在多个 CentOS 7 生产环境里亲手部署、压测、监控、调优、排障后沉淀下来的完整实践路径。没有概念堆砌只有每一步为什么这么配、参数怎么算、错在哪、怎么修。2. 整体架构设计与方案选型为什么放弃 pgpool-II坚持用 pgbouncer 应用层路由2.1 三种主流读写分离路径的真实对比在 CentOS 7 上实现 Postgres 读写分离业内常见方案有三类数据库代理层如 pgpool-II、ProxySQL、应用连接池层如 pgbouncer 配合应用路由逻辑、以及纯应用层控制ORM 手动指定数据源。我们曾对这三类方案在某中型物流调度系统日均 80 万订单峰值 QPS 1200上做过为期两周的对比压测结论非常明确方案类型部署复杂度故障隔离性一致性保障难度CentOS 7 兼容稳定性维护成本pgpool-II★★★★☆需额外安装、配置 health check、load balance、watchdog★★☆☆☆代理单点故障且自身无状态同步机制主从切换时易出现连接混乱★★☆☆☆内置“弱一致性”模式但无法精确控制单条 SQL 的读库选择事务内混用主从极易出错★★★☆☆RPM 包老旧官方源仅支持到 PG 10自行编译易与 systemd 服务单元冲突高需专职 DBA 监控其内部连接池、健康检查日志pgbouncer 应用路由★★★☆☆pgbouncer 本身极轻量重点在应用侧逻辑★★★★☆pgbouncer 仅做连接复用不参与 SQL 解析故障完全隔离★★★★☆应用可精确控制每个 DAO 方法的 target事务内强制走主库查询可按策略走从库★★★★★EPEL 源原生支持systemd 单元文件规范SELinux 策略明确中开发需理解路由规则但逻辑清晰调试方便纯应用层控制★★☆☆☆无需额外组件全靠代码★★★★★零中间件故障面最小★★★★★完全由业务代码决定可做到 per-query 级别控制★★★★★与 OS 无关高侵入性强ORM 升级易破坏路由逻辑测试覆盖难提示我们最终选择了pgbouncer 应用层路由的组合。这不是技术洁癖而是基于 CentOS 7 的运维现实——它要求方案足够“透明”、足够“可诊断”。pgpool-II 像一个黑盒当连接超时时你得在它的日志、PostgreSQL 的日志、Linux 的 netstat 输出之间来回跳转而 pgbouncer 的日志默认就记录了每个连接的来源 IP、目标数据库、认证方式、甚至客户端发送的第一条 SQL开启log_connections on且log_disconnections on配合journalctl -u pgbouncer一条命令就能定位问题源头。2.2 为什么 pgbouncer 是 CentOS 7 下最稳妥的连接池选择pgbouncer 的核心价值在于它完美契合 CentOS 7 的系统哲学小而专、配置驱动、日志详尽、与 systemd 深度集成。它不做 SQL 解析不尝试理解你的业务逻辑只做三件事接收客户端连接、复用后端连接、转发流量、记录一切。这种“克制”让它在 CentOS 7 的严苛环境下异常稳定。资源占用极低一个运行中的 pgbouncer 实例内存常驻约 15MBCPU 占用常年低于 0.3%这对资源有限的 CentOS 7 虚拟机至关重要。我们曾将它和 PostgreSQL 主实例部署在同一台 4C8G 的云主机上持续运行 11 个月未发生一次因 pgbouncer 导致的 OOM Kill。SELinux 友好CentOS 7 默认启用 SELinux而很多中间件会因上下文标签context不匹配被拦截。pgbouncer 的 EPEL RPM 包已预置了正确的pgbouncer_exec_t类型和postgresql_port_t网络端口策略只需执行setsebool -P pgbouncer_connect_any on即可允许其连接任意 PostgreSQL 端口无需手动写.te策略文件。systemd 服务单元健壮其/usr/lib/systemd/system/pgbouncer.service文件定义了标准的Restarton-failure、RestartSec10、LimitNOFILE65536并正确设置了EnvironmentFile/etc/sysconfig/pgbouncer来加载环境变量。这意味着即使你误操作导致 pgbouncer 崩溃systemd 会在 10 秒后自动拉起并继承所有配置业务连接中断时间控制在秒级。配置即文档/etc/pgbouncer/pgbouncer.ini文件本身就是一个极佳的配置说明书。每个 section[databases],[users],[pgbouncer]都有详细注释参数名直白如default_pool_size 20、min_pool_size 5、server_reset_query DISCARD ALL无需查外部手册。更重要的是它支持include语法你可以把敏感的用户密码单独放在/etc/pgbouncer/userlist.txt权限600并通过auth_file /etc/pgbouncer/userlist.txt引入既安全又便于 Ansible 管理。注意pgbouncer 的pool_mode是关键。我们严格采用transaction模式而非session或statement。原因在于session模式会让一个客户端连接长期绑定到同一个后端连接若该后端连接指向从库而客户端后续发起 UPDATEpgbouncer 会直接报错ERROR: cannot execute INSERT in a read-only transaction这虽能阻止错误但属于“事后拦截”增加了应用层的异常处理负担transaction模式则保证每个事务都获取一个干净的后端连接应用层可在事务开始前就明确指定目标主 or 从pgbouncer 只负责高效复用逻辑更清晰错误更早暴露。2.3 架构全景图三层解耦各司其职最终落地的架构是一个清晰的三层模型┌─────────────────────┐ ┌───────────────────────────────────────────────────┐ │ 应用层 │ │ pgbouncer (CentOS 7) │ │ • Spring Boot App │───▶│ • 监听 6432对外 │ │ • 自定义 RoutingDataSource │ │ • 配置两个逻辑库 │ │ • 事务内强制 useMaster() │ │ - master_db → 指向 192.168.1.10:5432 (主) │ │ • 查询方法标注 ReadOnly │ │ - slave_db → 指向 192.168.1.11:5432 (从) │ └─────────────────────┘ │ • auth_file 指向 /etc/pgbouncer/userlist.txt │ └───────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────┐ │ PostgreSQL 集群 (CentOS 7) │ │ • 主库 (192.168.1.10): │ │ - postgresql.conf: wal_levellogical, max_wal_senders10 │ │ - pg_hba.conf: host replication replicator ... trust │ │ • 从库 (192.168.1.11): │ │ - postgresql.conf: primary_conninfohost192.168.1.10... │ │ - recovery.signal 存在trigger_file 未设置 │ └───────────────────────────────────────────────────┘这个设计的核心思想是让每一层只解决自己领域的问题。应用层负责“业务意图”的表达我要读还是写pgbouncer 负责“连接资源”的高效调度PostgreSQL 自身负责“数据同步”的最终一致性。没有魔法只有清晰的责任边界。3. 核心细节解析与实操要点CentOS 7 环境下不可绕过的 7 个生死关3.1 关卡一SELinux 策略——那个让你连接 5432 失败却查不到日志的隐形杀手在 CentOS 7 上90% 的“数据库连不上”问题根源不在 PostgreSQL而在 SELinux。当你执行psql -h 192.168.1.10 -U appuser mydb报错psql: could not connect to server: Connection refused第一反应往往是检查postgresql.conf的listen_addresses和pg_hba.conf但很可能SELinux 已经默默拦截了所有入站连接。验证方法极其简单# 查看当前 SELinux 状态 sestatus # 检查是否有与 PostgreSQL 相关的拒绝日志无需重启服务 sudo ausearch -m avc -ts recent | grep postgresql # 或者更直接 sudo grep avc.*denied /var/log/audit/audit.log | grep postgresql如果输出类似typeAVC msgaudit(1712345678.123:456): avc: denied { name_connect } for pid1234 commpostgres dest5432 scontextsystem_u:system_r:postgresql_t:s0 tcontextsystem_u:object_r:postgresql_port_t:s0 tclasstcp_socket那就坐实了。解决方案不是关闭 SELinux这是运维大忌而是精准授权# 1. 允许 PostgreSQL 进程监听 5432 端口通常已默认允许 sudo semanage port -a -t postgresql_port_t -p tcp 5432 2/dev/null || true # 2. 关键允许 pgbouncer 连接到远程 PostgreSQL默认只允许本地 sudo setsebool -P pgbouncer_connect_any on # 3. 如果主从之间使用非标准端口如 5433需额外授权 sudo semanage port -a -t postgresql_port_t -p tcp 5433 2/dev/null || true实操心得我曾经在一个新装的 CentOS 7 服务器上花了整整一个下午排查 pgbouncer 无法连接从库的问题。telnet 192.168.1.11 5432通psql -h 192.168.1.11 -U replicator也通唯独 pgbouncer 的日志里全是connection failed: Connection refused。最后执行ausearch才发现 SELinux 拦截。教训是在 CentOS 7 上部署任何网络服务第一步永远是ausearch -m avc -ts today第二步才是查服务配置。3.2 关卡二firewalld 端口白名单——别让防火墙成为你的第一个背锅侠CentOS 7 默认启用 firewalld其规则优先级高于 iptables。很多人习惯性地systemctl stop firewalld来“快速验证”但这在生产环境是自杀行为。正确的做法是为每个服务显式开放所需端口。PostgreSQL 主从集群涉及三个关键端口5432PostgreSQL 默认服务端口主库监听从库也监听用于只读查询6432pgbouncer 监听端口应用连接此端口5432 的备用端口可选如果主从共用一台机器做测试需为从库分配如 5433开放命令如下# 永久开放 pgbouncer 端口供应用连接 sudo firewall-cmd --permanent --add-port6432/tcp # 永久开放主库端口供 pgbouncer 连接主库 sudo firewall-cmd --permanent --add-port5432/tcp # 永久开放从库端口供 pgbouncer 连接从库若从库在独立机器上 sudo firewall-cmd --permanent --add-source192.168.1.11/32 --permanent sudo firewall-cmd --permanent --add-port5432/tcp --permanent # 重载规则立即生效 sudo firewall-cmd --reload # 验证 sudo firewall-cmd --list-ports注意--add-source是关键。它表示“只允许来自 192.168.1.11 这台机器的连接访问本机的 5432 端口”这比--add-port更安全因为它限制了连接源避免了主库端口被公网扫描的风险。在生产环境主库的pg_hba.conf也应严格限制replication用户的来源 IP形成双重防护。3.3 关卡三PostgreSQL 主库配置——wal_level 和 max_wal_senders 的取值逻辑wal_level和max_wal_senders是流复制的基石但它们的取值不是拍脑袋决定的。wal_level决定了 WAL 日志记录的详细程度。CentOS 7 上推荐设为logical而非replica。原因在于replica足够支撑物理复制即我们的从库模式但它不记录足够的信息来支持逻辑解码Logical Decoding而逻辑解码是未来做 CDCChange Data Capture或对接 Kafka 的基础能力。logical级别兼容replica且开销增加微乎其微实测 WAL 日志体积增长 3%属于“一次配置长期受益”。hot_standby已被弃用archive仅用于归档都不满足流复制需求。max_wal_senders指主库最多允许多少个并发的 WAL 发送进程。它的值必须 ≥ 从库数量 预留数。计算公式为max_wal_senders N_slaves N_reserved其中N_reserved至少为 2用于应对临时的pg_basebackup备份、pg_receivewal归档等维护操作。例如你有 1 个主库 2 个从库则max_wal_senders 2 2 4。设得太小从库会报错FATAL: could not send replication command: ERROR: all replication slots are full设得太大会浪费少量内存每个 sender 进程约占用 1MB 内存。修改/var/lib/pgsql/data/postgresql.conf# --- Write Ahead Log --- wal_level logical # minimal, replica, or logical max_wal_senders 4 # max number of walsender processes max_replication_slots 4 # must max_wal_senders, for slot safety wal_keep_segments 64 # deprecated in PG13, use wal_keep_size instead # wal_keep_size 128MB # for PG13, keep WAL files for at least this much space提示wal_keep_segments在 PostgreSQL 13 中已被wal_keep_size取代。如果你的 CentOS 7 上安装的是 PG 12 或更早版本用前者PG 13 则用后者。wal_keep_size的单位是字节B/KB/MB/GB128MB是一个经过压测的保守值足以应对从库短暂断连后的追赶catchup。3.4 关卡四pg_hba.conf 的认证链路——顺序、协议、信任一个都不能错pg_hba.conf是 PostgreSQL 的“门禁系统”其规则是自上而下匹配一旦匹配成功即停止搜索。一个常见的致命错误是把宽泛的host all all 0.0.0.0/0 md5放在了针对replication用户的规则之前。正确的pg_hba.conf片段放在/var/lib/pgsql/data/pg_hba.conf末尾应如下# TYPE DATABASE USER ADDRESS METHOD # local is for Unix domain socket connections. local all all peer # IPv4 local connections: host all all 127.0.0.1/32 md5 host replication replicator 127.0.0.1/32 md5 # IPv4 remote connections (for application and pgbouncer): host all appuser 192.168.1.0/24 md5 host all pgbouncer 192.168.1.0/24 md5 # Replication connections from standby servers (CRITICAL ORDER!) host replication replicator 192.168.1.11/32 trust host replication replicator 192.168.1.12/32 trust # Allow replication connections from any host in the subnet (if you have many standbys) # host replication replicator 192.168.1.0/24 scram-sha-256关键点解析replication规则必须放在all规则之后因为replication是一个特殊的伪数据库名它不对应真实数据库只用于复制连接。如果把它放在host all ...之后那么所有来自192.168.1.11的连接都会先匹配到host all ...规则然后尝试用appuser的密码去登录replication数据库必然失败。METHOD选trust还是scram-sha-256对于内网环境trust是安全且高效的。replicator用户的密码只在primary_conninfo字符串中使用而该字符串存储在从库的postgresql.conf中其文件权限应为600chmod 600 /var/lib/pgsql/data/postgresql.conf。trust省去了密码校验的开销让 WAL 传输更流畅。如果合规要求必须加密则用scram-sha-256但需确保主库已创建该用户并设定了强密码。ADDRESS必须精确192.168.1.11/32表示只允许这一个 IP比192.168.1.0/24更安全。在生产环境宁可多写几行也不要图省事用大网段。3.5 关卡五从库初始化——pg_basebackup 的静默陷阱与恢复点控制从库不能凭空产生必须通过pg_basebackup从主库拉取一个基础备份base backup。这个过程看似简单但有两个静默陷阱陷阱一-X stream参数的必要性pg_basebackup -D /var/lib/pgsql/data -h 192.168.1.10 -U replicator -P -R -X stream中的-X stream至关重要。它表示“在备份过程中同时启动一个 WAL 流来接收备份期间产生的新 WAL”。如果没有它备份结束后从库会缺少备份结束到recovery.signal创建这段时间的 WAL导致启动时报错could not locate a valid checkpoint record。-R参数会自动生成standby.signal文件和postgresql.auto.conf中的primary_conninfo但前提是备份过程是“流式”的。陷阱二-S参数与恢复点Recovery Point如果你想让从库启动后只恢复到某个特定时间点Point-in-Time Recovery, PITR必须在pg_basebackup时指定-Sslot name并配合pg_create_physical_replication_slot()。但在纯粹的读写分离场景下我们不需要 PITR只需要实时同步因此-S非必需。但要注意-R生成的postgresql.auto.conf中的primary_conninfo字符串必须手动检查并确保application_name参数存在例如primary_conninfo host192.168.1.10 port5432 userreplicator passwordxxx application_namestandby1application_name是你在主库pg_stat_replication视图中识别该从库的唯一标识也是后续监控延迟的关键字段。执行完整流程# 1. 在主库上创建 replication 用户如果尚未创建 psql -U postgres -c CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD strong_password; # 2. 在从库机器上清空数据目录谨慎 sudo systemctl stop postgresql sudo rm -rf /var/lib/pgsql/data/* sudo chown postgres:postgres /var/lib/pgsql/data # 3. 执行流式基础备份关键-X stream -R sudo -u postgres pg_basebackup -D /var/lib/pgsql/data -h 192.168.1.10 -U replicator -P -R -X stream -v # 4. 检查生成的配置 sudo -u postgres cat /var/lib/pgsql/data/postgresql.auto.conf # 确认包含 primary_conninfo 和 application_name # 5. 启动从库 sudo systemctl start postgresql3.6 关卡六pgbouncer 配置——databases和users的映射艺术pgbouncer 的灵魂在于/etc/pgbouncer/pgbouncer.ini中的[databases]和[users]配置。它们不是简单的字符串替换而是一套映射规则。[databases]配置定义了“客户端看到的数据库名”与“实际连接的后端数据库”的映射关系。对于读写分离我们需要两个逻辑库[databases] # 逻辑库名 实际连接字符串 master_db host192.168.1.10 port5432 dbnamemyapp userappuser passwordxxx slave_db host192.168.1.11 port5432 dbnamemyapp userappuser passwordxxx这里master_db和slave_db是应用代码里DataSource的 JNDI 名或 URL 中的databaseName。应用连接pgbouncer:6432时指定databasemaster_dbpgbouncer 就会将其路由到192.168.1.10:5432。[users]配置定义了“客户端连接时使用的用户名”与“后端数据库实际认证凭据”的映射。为了安全我们不把明文密码写在databases里而是用auth_file[pgbouncer] auth_type file auth_file /etc/pgbouncer/userlist.txt ... [databases] master_db host192.168.1.10 port5432 dbnamemyapp slave_db host192.168.1.11 port5432 dbnamemyapp/etc/pgbouncer/userlist.txt内容为appuser md5d1e0f2a3b4c5d6e7f8a9b0c1d2e3f4a5这个md5值是md5 password username的 MD5 哈希可以用pg_md5工具生成echo -n mypasswordappuser | md5sum | cut -d -f1 # 输出d1e0f2a3b4c5d6e7f8a9b0c1d2e3f4a5 # 然后拼成 md5 上述字符串注意userlist.txt的权限必须是600且属主为pgbouncer用户通常是postgres否则 pgbouncer 启动时会报错auth file permissions are too open。3.7 关卡七应用层路由——Spring Boot 中AbstractRoutingDataSource的实战封装有了 pgbouncer 的逻辑库应用层必须能智能地选择master_db还是slave_db。在 Spring Boot 中AbstractRoutingDataSource是标准解法但网上很多示例是“玩具级”的无法应对真实业务的复杂性。我们封装了一个生产就绪的RoutingDataSourcepublic class RoutingDataSource extends AbstractRoutingDataSource { private static final String MASTER master_db; private static final String SLAVE slave_db; Override protected Object determineCurrentLookupKey() { // 1. 事务内强制走主库 if (TransactionSynchronizationManager.isActualTransactionActive()) { return MASTER; } // 2. 检查线程局部变量ReadOnly 注解触发 String key DataSourceContextHolder.getDataSourceType(); if (key ! null) { return key; } // 3. 默认走主库安全兜底 return MASTER; } }配套的DataSourceContextHolderpublic class DataSourceContextHolder { private static final ThreadLocalString CONTEXT_HOLDER new ThreadLocal(); public static void setDataSourceType(String dataSourceType) { CONTEXT_HOLDER.set(dataSourceType); } public static String getDataSourceType() { return CONTEXT_HOLDER.get(); } public static void clearDataSourceType() { CONTEXT_HOLDER.remove(); } }以及一个ReadOnly注解和 AOP 切面Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface ReadOnly { } Aspect Component public class ReadOnlyAspect { Around(annotation(readOnly)) public Object proceedReadOnly(ProceedingJoinPoint joinPoint, ReadOnly readOnly) throws Throwable { DataSourceContextHolder.setDataSourceType(DataSourceContextHolder.SLAVE); try { return joinPoint.proceed(); } finally { DataSourceContextHolder.clearDataSourceType(); } } }使用时Service public class OrderService { ReadOnly // 此方法内的所有查询都将路由到 slave_db public ListOrder findRecentOrders() { return orderMapper.selectRecent(); } Transactional // 此方法内的所有操作包括查询都走 master_db public void createOrder(Order order) { orderMapper.insert(order); // 写 orderMapper.selectById(order.getId()); // 即使是读也走主库保证强一致 } }实操心得这个设计的关键在于“事务优先级最高”。很多初学者会把ReadOnly和Transactional同时加在一个方法上期望“读走从库写走主库”这是错误的。Spring 的事务管理器会在方法入口就开启事务此时determineCurrentLookupKey()已经返回MASTER后续的ReadOnly切面再设置SLAVE也晚了。所以读写分离的粒度必须是方法级而不是 SQL 级。一个方法要么全读ReadOnly要么全写Transactional或者混合但接受主库读默认行为。4. 实操过程与核心环节实现从零开始手把手完成 CentOS 7 部署4.1 环境准备与软件安装全程 root 或 sudo假设你有两台 CentOS 7 服务器主库服务器IP192.168.1.10主机名pg-master从库服务器IP192.168.1.11主机名pg-slave应用服务器IP192.168.1.20将部署 pgbouncer步骤 1在所有服务器上启用 EPEL 源并安装基础包# 安装 EPEL企业级额外包源 sudo yum install -y epel-release # 更新系统可选但推荐 sudo yum update -y # 安装 PostgreSQL 13以 13 为例CentOS 7 默认源较旧需用官方源 sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo yum install -y postgresql13-server postgresql13-contrib # 初始化数据库仅主库执行 sudo /usr/pgsql-13/bin/postgresql-13-setup initdb # 安装 pgbouncer所有需运行 pgbouncer 的机器 sudo yum install -y pgbouncer步骤 2配置主库192.168.1.10# 1. 修改 postgresql.conf sudo sed -i s/^#wal_level replica/wal_level logical/ /var/lib/pgsql/13/data/postgresql.conf sudo sed -i s/^#max_wal_senders 10/max_wal_senders 4/ /var/lib/pgsql/13/data/postgresql.conf sudo sed -i s/^#max_replication_slots 10/max_replication_slots 4/ /var/lib/pgsql/13/data/postgresql.conf sudo sed -i s/^#wal_keep_segments 0/wal_keep_segments 64/ /var/lib/pgsql/13/data/postgresql.conf sudo sed -i s/^#listen_addresses localhost/listen_addresses 192.168.1.10,localhost/ /var/lib/pgsql/13/data/postgresql.conf sudo sed -i s/^#port 543

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑