外观
PostgreSQL 主从复制(流复制)
核心概念
PostgreSQL主从复制是一种数据冗余机制,通过将主数据库(Master)的数据变更实时同步到一个或多个从数据库(Slave/Standby),实现数据备份、读写分离和高可用性。
流复制工作原理
流复制(Streaming Replication)是PostgreSQL 9.0引入的物理复制技术,其工作原理如下:
- 主库将事务写入WAL(Write-Ahead Log)日志
- 从库通过WAL接收器(walreceiver)连接到主库的WAL发送器(walsender)
- 主库实时将WAL记录流发送到从库
- 从库应用收到的WAL记录,保持与主库数据一致
- 从库可以处于两种模式:
- 恢复模式(Recovery Mode):只读,不能接受写操作
- 热备模式(Hot Standby):只读,可以接受查询操作
复制类型
| 复制类型 | 描述 | 适用场景 |
|---|---|---|
| 异步复制 | 主库不等待从库确认收到WAL记录 | 对数据一致性要求不高,追求高性能 |
| 同步复制 | 主库等待从库确认收到并写入WAL记录 | 对数据一致性要求高,如金融系统 |
| 半同步复制 | 主库等待至少一个从库确认收到WAL记录 | 平衡性能和一致性的场景 |
配置步骤
1. 环境准备
| 角色 | IP地址 | 操作系统 | PostgreSQL版本 | 数据目录 |
|---|---|---|---|---|
| 主库 | 192.168.1.10 | CentOS 7 | 15 | /var/lib/pgsql/15/data |
| 从库 | 192.168.1.11 | CentOS 7 | 15 | /var/lib/pgsql/15/data |
2. 主库配置
2.1 修改postgresql.conf
bash
# 启用WAL归档
archive_mode = on
archive_command = 'cp %p /var/lib/pgsql/15/archive/%f'
# 配置WAL级别(流复制需要replica或更高)
wal_level = replica
# 最大WAL发送进程数(建议与从库数量匹配)
max_wal_senders = 5
# 最大复制槽数量
max_replication_slots = 5
# 同步复制超时时间
wal_sender_timeout = 60s
# 启用热备(从库可以接受查询)
hot_standby = on2.2 创建归档目录
bash
mkdir -p /var/lib/pgsql/15/archive
chown -R postgres:postgres /var/lib/pgsql/15/archive
chmod 700 /var/lib/pgsql/15/archive2.3 修改pg_hba.conf
bash
# 允许从库连接进行复制
host replication replicauser 192.168.1.11/32 scram-sha-256
host replication replicauser 192.168.1.12/32 scram-sha-2562.4 创建复制用户
sql
-- 以postgres用户身份连接到主库
psql -h localhost -U postgres
-- 创建复制用户
CREATE ROLE replicauser WITH REPLICATION LOGIN PASSWORD 'replicapass';
-- 重载配置
SELECT pg_reload_conf();3. 从库配置
3.1 停止从库PostgreSQL服务
bash
systemctl stop postgresql-153.2 清空从库数据目录
bash
rm -rf /var/lib/pgsql/15/data/*3.3 使用pg_basebackup初始化从库
bash
# 从主库复制基础备份到从库
pg_basebackup -h 192.168.1.10 -U replicauser -D /var/lib/pgsql/15/data -Fp -Xs -Pv参数说明:
-h:主库IP地址-U:复制用户-D:从库数据目录-Fp:使用普通文件格式-Xs:流式传输WAL文件-Pv:显示进度和详细信息
3.4 创建recovery.signal文件
bash
# 创建recovery.signal文件,指示从库处于恢复模式
touch /var/lib/pgsql/15/data/recovery.signal3.5 创建standby.signal文件(PostgreSQL 12+)
bash
# 创建standby.signal文件,指示从库为备用节点
touch /var/lib/pgsql/15/data/standby.signal3.6 配置recovery.conf(PostgreSQL 11及以下)或postgresql.auto.conf(PostgreSQL 12+)
对于PostgreSQL 12+,配置会自动写入postgresql.auto.conf。如果需要手动配置,可以创建primary_conninfo参数:
bash
# 编辑postgresql.auto.conf,添加主库连接信息
echo "primary_conninfo = 'host=192.168.1.10 port=5432 user=replicauser password=replicapass application_name=standby1'" >> /var/lib/pgsql/15/data/postgresql.auto.conf
# 配置从库为只读模式
echo "hot_standby = on" >> /var/lib/pgsql/15/data/postgresql.auto.conf3.7 设置文件权限
bash
chown -R postgres:postgres /var/lib/pgsql/15/data
chmod 700 /var/lib/pgsql/15/data3.8 启动从库PostgreSQL服务
bash
systemctl start postgresql-15复制监控与管理
1. 监控复制状态
1.1 在主库上监控
sql
-- 查看WAL发送进程状态
SELECT * FROM pg_stat_replication;
-- 查看复制槽状态
SELECT * FROM pg_replication_slots;
-- 查看WAL归档状态
SELECT * FROM pg_stat_archiver;1.2 在从库上监控
sql
-- 查看复制状态
SELECT * FROM pg_stat_wal_receiver;
-- 查看恢复状态
SELECT * FROM pg_stat_wal_receiver;
-- 查看复制延迟
SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;
-- 查看从库是否处于只读模式
SHOW transaction_read_only;2. 常用管理命令
2.1 主库命令
sql
-- 手动切换WAL日志
SELECT pg_switch_wal();
-- 创建复制槽
SELECT * FROM pg_create_physical_replication_slot('slot_name');
-- 删除复制槽
SELECT * FROM pg_drop_replication_slot('slot_name');2.2 从库命令
sql
-- 取消恢复模式(使从库变为独立数据库)
pg_ctl promote -D /var/lib/pgsql/15/data
-- 或在从库中执行
SELECT pg_promote();3. 复制监控工具
3.1 pg_stat_replication视图详解
| 列名 | 描述 |
|---|---|
| pid | WAL发送进程ID |
| usesysid | 复制用户ID |
| usename | 复制用户名 |
| application_name | 从库应用名称 |
| client_addr | 从库IP地址 |
| client_hostname | 从库主机名 |
| client_port | 从库端口 |
| backend_start | 连接开始时间 |
| backend_xmin | 从库最后接收的事务ID |
| state | 复制状态(streaming, catching up, etc.) |
| sent_lsn | 已发送的WAL位置 |
| write_lsn | 从库已写入的WAL位置 |
| flush_lsn | 从库已刷新到磁盘的WAL位置 |
| replay_lsn | 从库已应用的WAL位置 |
| write_lag | 写入延迟 |
| flush_lag | 刷新延迟 |
| replay_lag | 应用延迟 |
| sync_priority | 同步优先级 |
| sync_state | 同步状态(async, sync, quorum) |
同步复制配置
1. 异步复制 vs 同步复制
| 特性 | 异步复制 | 同步复制 |
|---|---|---|
| 性能 | 高 | 较低 |
| 数据一致性 | 可能丢失数据 | 数据不丢失 |
| 故障影响 | 主库故障可能丢失最近事务 | 主库故障不会丢失数据 |
| 配置复杂度 | 低 | 中 |
2. 配置同步复制
2.1 修改主库postgresql.conf
bash
# 配置同步复制模式
synchronous_commit = on
# 指定同步从库名称列表
synchronous_standby_names = 'standby1,standby2'2.2 验证同步复制状态
sql
-- 在主库上查看同步状态
SELECT usename, application_name, state, sync_state FROM pg_stat_replication;常见问题与故障排除
1. 从库连接失败
症状:
FATAL: could not connect to the primary server: FATAL: no pg_hba.conf entry for replication connection from host "192.168.1.11", user "replicauser", SSL off解决方法:
- 检查pg_hba.conf是否允许从库IP连接
- 检查复制用户密码是否正确
- 检查主库防火墙是否开放5432端口
2. 复制延迟过大
症状:
replication_delay | 00:05:30.123456解决方法:
- 检查网络带宽是否足够
- 检查主库WAL生成速率是否过高
- 检查从库IO性能是否瓶颈
- 调整从库参数:
hot_standby_feedback = on
3. WAL归档失败
症状:
WARNING: archive command failed with exit code 1
DETAIL: The failed archive command was: cp pg_wal/000000010000000000000001 /var/lib/pgsql/15/archive/000000010000000000000001解决方法:
- 检查归档目录权限
- 检查归档目录磁盘空间
- 检查归档命令语法
4. 从库无法启动
症状:
FATAL: database system identifier differs between the primary and standby解决方法:
- 确保从库是使用pg_basebackup从主库初始化的
- 检查从库数据目录是否正确清空
- 重新执行pg_basebackup初始化从库
最佳实践
1. 硬件配置
- 主从库使用相同或相似的硬件配置
- 使用SSD存储提高IO性能
- 确保主从库之间网络带宽充足(建议1Gbps以上)
2. 配置优化
- 使用复制槽避免WAL日志丢失
- 启用hot_standby_feedback避免查询冲突
- 定期监控复制延迟,设置合理的告警阈值
- 使用同步复制或半同步复制提高数据安全性
3. 监控与告警
- 监控复制延迟,设置告警阈值(如>30秒)
- 监控WAL发送和接收进程状态
- 监控归档命令执行情况
- 定期测试主从切换,确保故障切换可行
4. 安全配置
- 为复制用户设置强密码
- 限制复制连接的IP地址范围
- 使用SSL加密复制连接
- 定期轮换复制用户密码
5. 备份策略
- 从库可以作为备份源,减少主库备份压力
- 定期在从库上执行基础备份
- 结合WAL归档实现PITR(Point-In-Time Recovery)
常见问题(FAQ)
Q1:如何检查主从复制是否正常工作?
A1:可以通过以下方法检查:
sql
-- 在主库上查看复制状态
SELECT * FROM pg_stat_replication;
-- 在从库上查看复制延迟
SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;Q2:主从复制支持读写分离吗?
A2:是的,PostgreSQL主从复制天然支持读写分离:
- 主库处理写操作和实时读操作
- 从库处理报表查询、数据分析等只读操作
Q3:如何增加新的从库?
A3:增加新从库的步骤:
- 在主库的pg_hba.conf中添加新从库的IP地址
- 在主库上重载配置
- 在新从库上使用pg_basebackup从主库初始化
- 配置新从库的recovery.signal和postgresql.auto.conf
- 启动新从库
Q4:主库故障后如何将从库提升为主库?
A4:主库故障后提升从库的步骤:
- 停止主库(如果还在运行)
- 在从库上执行
pg_ctl promote -D /var/lib/pgsql/15/data - 修改应用连接字符串,指向新主库
- 重新配置其他从库连接到新主库
Q5:如何配置半同步复制?
A5:配置半同步复制的步骤:
- 安装半同步复制扩展
- 修改postgresql.conf启用半同步复制
- 配置同步 standby 名称
- 重载配置
Q6:复制槽有什么作用?
A6:复制槽的作用:
- 确保主库保留从库需要的所有WAL日志
- 防止主库过早删除从库尚未接收的WAL日志
- 支持从库离线后重新连接时能够追上主库
Q7:如何监控复制性能?
A7:可以监控以下指标:
- 复制延迟
- WAL生成速率
- WAL发送和接收速率
- 从库IO利用率
- 网络带宽使用率
Q8:主从复制会影响主库性能吗?
A8:主从复制对主库性能的影响:
- 会增加主库的CPU和内存使用
- 会增加主库的网络带宽消耗
- 异步复制对主库性能影响较小
- 同步复制会增加主库事务提交延迟
Q9:如何测试主从复制的可靠性?
A9:测试主从复制可靠性的方法:
- 执行大量写操作,检查从库是否能及时同步
- 模拟主库故障,测试从库提升流程
- 测试从库故障恢复后能否重新连接主库
- 测试网络中断后复制能否自动恢复
Q10:PostgreSQL 15有哪些复制新特性?
A10:PostgreSQL 15复制新特性:
- 支持并行应用WAL日志,提高从库复制速度
- 增强了复制槽管理功能
- 改进了WAL发送和接收性能
- 支持更灵活的同步复制配置
故障切换案例
场景:主库突然宕机
故障现象:
- 主库服务器断电
- 应用连接失败
- 从库复制中断
处理步骤:
确认主库故障:
bashping 192.168.1.10 # 检查网络连接 ssh 192.168.1.10 # 尝试SSH登录 systemctl status postgresql-15 # 检查PostgreSQL状态提升从库为主库:
bash# 在从库上执行 pg_ctl promote -D /var/lib/pgsql/15/data验证新主库状态:
sql-- 检查是否已提升为主库 SELECT pg_is_in_recovery(); -- 应返回false -- 检查是否可写 SHOW transaction_read_only; -- 应返回off更新应用连接配置:
- 修改应用配置文件中的数据库连接地址为新主库IP
- 重启应用或重载配置
重新配置其他从库:
- 停止其他从库
- 清空数据目录
- 使用pg_basebackup从新主库初始化
- 重启从库
修复原主库:
- 修复硬件故障
- 重新安装操作系统和PostgreSQL
- 将原主库配置为新主库的从库
