过早闭环正在扼杀你的内容生命力:你设计了“结构性不完整“吗?
2026/6/4 15:28:28
本文档总结了在 Docker 容器环境中配置 PostgreSQL 16 主从流复制(Streaming Replication)的完整流程、常见问题及解决方案。
# 进入主服务器容器dockerexec-it postgresql-16 psql -U postgres# 创建复制用户CREATEUSERreplication_user WITH REPLICATION PASSWORD'passw0rd';# 退出\q# 在容器内编辑配置文件dockerexec-it postgresql-16bashvi/var/lib/postgresql/data/pgdata/postgresql.conf添加或修改以下配置:
# 启用 WAL 归档(必须) wal_level = replica # 设置最大 WAL 发送进程数(至少为 1) max_wal_senders = 10 # 设置最大复制槽数(可选,用于逻辑复制) max_replication_slots = 10 # 启用热备份(允许从服务器执行只读查询) hot_standby = on或者使用 ALTER SYSTEM 命令:
dockerexecpostgresql-16 psql -U postgres -c"ALTER SYSTEM SET wal_level = 'replica';"dockerexecpostgresql-16 psql -U postgres -c"ALTER SYSTEM SET max_wal_senders = 10;"dockerexecpostgresql-16 psql -U postgres -c"ALTER SYSTEM SET hot_standby = 'on';"# 在容器内编辑dockerexec-it postgresql-16bashvi/var/lib/postgresql/data/pgdata/pg_hba.conf在文件末尾添加(替换为从服务器实际 IP):
# 允许从服务器连接进行流复制 host replication replication_user 192.168.1.100/32 md5或者直接在主服务器上执行:
# 查看当前配置dockerexecpostgresql-16cat/var/lib/postgresql/data/pgdata/pg_hba.conf|grepreplication# 如果不存在,需要手动添加dockerexec-it postgresql-16bashecho"host replication replication_user 192.168.1.100/32 md5">>/var/lib/postgresql/data/pgdata/pg_hba.confdockerrestart postgresql-16# 检查 wal_leveldockerexecpostgresql-16 psql -U postgres -c"SHOW wal_level;"# 应该返回: replica# 检查 max_wal_sendersdockerexecpostgresql-16 psql -U postgres -c"SHOW max_wal_senders;"# 应该返回: 10(或更大)# 检查监听地址dockerexecpostgresql-16 psql -U postgres -c"SHOW listen_addresses;"# 应该返回: * 或包含主服务器IPdockerstop postgresql-16# 备份现有数据(如果重要)mv/disk/data/postgres/pgdata /disk/data/postgres/pgdata_backup_$(date+%Y%m%d_%H%M%S)# 创建新的空数据目录mkdir-p /disk/data/postgres/pgdatachown-R999:999 /disk/data/postgres/pgdata# 验证目录为空ls-la /disk/data/postgres/pgdata# 应该只显示 . 和 .. 目录使用自动脚本(推荐):
sudobashpg16_recreate_slave_from_master.sh或手动执行:
dockerrun --rm\-v /disk/data/postgres:/var/lib/postgresql/data\-ePGPASSWORD=passw0rd\postgres:16\pg_basebackup\-h192.168.1.9\-p5432\-U replication_user\-D /var/lib/postgresql/data/pgdata\-F p\-X stream\-P\-R\-v参数说明:
-h: 主服务器 IP 地址-p: 主服务器端口(默认 5432)-U: 复制用户名-D: 目标数据目录(容器内的路径)-F p: 使用纯文本格式(plain format)-X stream: 启用流复制,在备份过程中流式传输 WAL-P: 显示进度-R: 自动创建standby.signal和postgresql.auto.conf文件-v: 详细输出# 检查关键文件ls-la /disk/data/postgres/pgdata/# 应该包含:# - PG_VERSION# - standby.signal# - postgresql.auto.conf# - base/ 目录# - global/ 目录# 检查 primary_conninfocat/disk/data/postgres/pgdata/postgresql.auto.conf|grepprimary_conninfo# 检查 standby.signalls-la /disk/data/postgres/pgdata/standby.signalchown-R999:999 /disk/data/postgres/pgdatadockerstart postgresql-16# 等待启动sleep5# 检查状态dockerexecpostgresql-16 pg_isready -U postgres# 查看复制连接dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_replication;"# 应该显示从服务器的连接信息,包括:# - pid: 进程ID# - application_name: 应用名称# - client_addr: 从服务器IP# - state: 状态(通常是 streaming)# - sync_state: 同步状态# - sent_lsn, write_lsn, flush_lsn, replay_lsn: WAL 位置# 检查恢复模式dockerexecpostgresql-16 psql -U postgres -c"SELECT pg_is_in_recovery();"# 应该返回: t (true)# 检查 WAL 接收器dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_wal_receiver;"# 应该显示:# - pid: WAL 接收器进程ID# - status: 状态(通常是 streaming)# - receive_start_lsn: 开始接收的 WAL 位置# - latest_end_lsn: 最新接收的 WAL 位置# - sender_host: 主服务器IP# - sender_port: 主服务器端口# 检查 WAL 位置dockerexecpostgresql-16 psql -U postgres -c" SELECT pg_last_wal_receive_lsn() AS receive_lsn, pg_last_wal_replay_lsn() AS replay_lsn, pg_last_wal_receive_lsn() - pg_last_wal_replay_lsn() AS lag_bytes; "# 在主服务器上创建测试数据库dockerexecpostgresql-16 psql -U postgres -c"CREATE DATABASE replication_test;"# 在主服务器上创建表并插入数据dockerexecpostgresql-16 psql -U postgres -d replication_test -c" CREATE TABLE test_table (id SERIAL PRIMARY KEY, name VARCHAR(100)); INSERT INTO test_table (name) VALUES ('test1'), ('test2'); "# 等待几秒钟让数据同步sleep3# 在从服务器上查询(应该能看到数据)dockerexecpostgresql-16 psql -U postgres -d replication_test -c"SELECT * FROM test_table;"错误信息:
FATAL: database system identifier differs between the primary and standby DETAIL: The primary's identifier is 7602832328514842668, the standby's identifier is 7602844093384110118.原因:
从服务器的数据目录不是从主服务器的正确备份创建的。可能原因:
pg_basebackup之前不是空的pg_basebackup执行失败但没有被注意到解决方案:
使用自动修复脚本:
sudobashpg16_recreate_slave_from_master.sh或手动修复:
# 1. 停止从服务器容器dockerstop postgresql-16# 2. 备份并删除旧数据目录mv/disk/data/postgres/pgdata /disk/data/postgres/pgdata_backup_$(date+%Y%m%d_%H%M%S)mkdir-p /disk/data/postgres/pgdatachown-R999:999 /disk/data/postgres/pgdata# 3. 验证目录为空ls-la /disk/data/postgres/pgdata# 应该只显示 . 和 ..# 4. 重新执行 pg_basebackupdockerrun --rm\-v /disk/data/postgres:/var/lib/postgresql/data\-ePGPASSWORD=was70ptf\postgres:16\pg_basebackup\-h192.168.1.9\-p5432\-U replication_user\-D /var/lib/postgresql/data/pgdata\-F p\-X stream\-P\-R\-v# 5. 设置权限chown-R999:999 /disk/data/postgres/pgdata# 6. 启动容器dockerstart postgresql-16错误信息:
FATAL: recovery aborted because of insufficient parameter settings DETAIL: max_connections = 100 is a lower setting than on the primary server, where its value was 200.原因:
从服务器的某些参数值小于主服务器,导致恢复失败。
解决方案:
在从服务器的postgresql.auto.conf中设置相同或更大的值:
# 检查主服务器的 max_connectionsdockerexecpostgresql-16 psql -U postgres -c"SHOW max_connections;"# 在从服务器上设置(在主服务器上执行,替换为从服务器IP)dockerexecpostgresql-16bash-c"echo 'max_connections = 200' >> /var/lib/postgresql/data/pgdata/postgresql.auto.conf"# 或者直接在主机上编辑echo"max_connections = 200">>/disk/data/postgres/pgdata/postgresql.auto.confchown999:999 /disk/data/postgres/pgdata/postgresql.auto.conf# 重启从服务器容器dockerrestart postgresql-16注意:pg16_recreate_slave_from_master.sh脚本会自动处理这个问题。
症状:
dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_wal_receiver;"# 返回: (0 rows)可能原因:
standby.signal文件不存在primary_conninfo配置错误解决方案:
ls-la /disk/data/postgres/pgdata/standby.signal# 如果不存在,创建它touch/disk/data/postgres/pgdata/standby.signalchown999:999 /disk/data/postgres/pgdata/standby.signalcat/disk/data/postgres/pgdata/postgresql.auto.conf|grepprimary_conninfo# 应该包含正确的主服务器IP、端口、用户名和密码# 在从服务器容器内测试dockerexecpostgresql-16 pg_isready -h192.168.1.9 -p5432-U replication_user# 在主服务器上dockerexecpostgresql-16cat/var/lib/postgresql/data/pgdata/pg_hba.conf|grepreplication# 应该包含从服务器IP的规则sudobashpg16_fix_wal_receiver.sh症状:
# 在主服务器上dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_replication;"# 返回: (0 rows)可能原因:
pg_hba.conf未允许从服务器连接wal_level或max_wal_senders配置不正确解决方案:
sudobashpg16_check_master_for_slave.shdockerexecpostgresql-16cat/var/lib/postgresql/data/pgdata/pg_hba.conf|grepreplication# 确保包含: host replication replication_user <从服务器IP>/32 md5dockerexecpostgresql-16 psql -U postgres -c"SHOW wal_level;"dockerexecpostgresql-16 psql -U postgres -c"SHOW max_wal_senders;"错误信息:
psql: error: connection to server at "192.168.1.9", port 5432 failed: Connection refused可能原因:
解决方案:
dockerps|greppostgresql-16dockerexecpostgresql-16 psql -U postgres -c"SHOW listen_addresses;"# 应该是 * 或包含主服务器IP# 在从服务器上ping192.168.1.9 telnet192.168.1.95432症状:
在主服务器上创建数据库和表后,从服务器上看不到。
可能原因:
pg_basebackup之前就存在数据解决方案:
# 在主服务器上dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_replication;"# 在从服务器上dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_wal_receiver;"# 主服务器dockerexecpostgresql-16 psql -U postgres -c"SELECT pg_current_wal_lsn();"# 从服务器dockerexecpostgresql-16 psql -U postgres -c"SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();"pg_basebackup之前创建的,需要重新创建从服务器:sudobashpg16_recreate_slave_from_master.sh关键点:
/disk/data/postgres->/var/lib/postgresql/data/disk/data/postgres/pgdata(容器内为/var/lib/postgresql/data/pgdata)pg_basebackup的-D参数必须使用容器内的路径:/var/lib/postgresql/data/pgdata错误示例:
# ❌ 错误:使用主机路径pg_basebackup -D /disk/data/postgres/pgdata...# ✅ 正确:使用容器内路径dockerrun --rm -v /disk/data/postgres:/var/lib/postgresql/data... pg_basebackup -D /var/lib/postgresql/data/pgdata...pg_basebackup创建的max_connections)必须 >= 主服务器的值postgresql.auto.conf中设置这些参数pg16_recreate_slave_from_master.sh脚本会自动处理pg_basebackup之前,目标目录必须为空pg_basebackup会失败或产生不一致的数据pg_hba.conf允许从服务器连接listen_addresses = *)999:999(PostgreSQL 容器用户)chown -R 999:999 /disk/data/postgres/pgdata设置权限pg_basebackup之后的变更pg_basebackup之前创建的数据库和表不会自动复制pg_basebackuppg16_diagnose_sync.sh: 诊断流复制同步问题pg16_check_master_for_slave.sh: 检查主服务器配置pg16_check_replication.sh: 检查从服务器复制状态pg16_recreate_slave_from_master.sh: 重新从主服务器创建从服务器(修复系统标识符不匹配)pg16_fix_wal_receiver.sh: 修复 WAL 接收器未启动问题pg16_fix_replication.sh: 修复常见复制问题pg16_setup_slave.sh: 从服务器初始设置pg16_quick_slave_setup.sh: 快速设置从服务器(简化版)pg16_test_replication.sh: 测试流复制功能pg16_setup_replication_test.sh: 创建测试数据库和表# 每天检查一次流复制状态dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_replication;"dockerexecpostgresql-16 psql -U postgres -c"SELECT * FROM pg_stat_wal_receiver;"# 检查 WAL 延迟dockerexecpostgresql-16 psql -U postgres -c" SELECT pg_last_wal_receive_lsn() AS receive_lsn, pg_last_wal_replay_lsn() AS replay_lsn, pg_last_wal_receive_lsn() - pg_last_wal_replay_lsn() AS lag_bytes; "pg_dump或使用 WAL 归档如果需要将从服务器提升为主服务器:
# 在从服务器上dockerexecpostgresql-16 psql -U postgres -c"SELECT pg_promote();"# 删除 standby.signalrm/disk/data/postgres/pgdata/standby.signal# 重启容器dockerrestart postgresql-16PostgreSQL 16 容器主从流复制的关键点:
wal_level = replica、max_wal_senders >= 1、pg_hba.conf允许从服务器连接pg_basebackup创建数据目录,确保目录为空,系统标识符匹配pg_basebackup使用容器内路径,挂载路径必须一致999:999遇到问题时,使用诊断脚本定位问题,然后使用相应的修复脚本解决。
文档版本: 1.0
最后更新: 2026-02-04
作者: AI Assistant