Postgresql主从复制
- 主备数据库启动,备库启动wal_receiver进程,wal进程向主库发送连接请求;
- 主库收到连接请求后启动wal_sender进程,并与wal_receiver进程建立tcp连接;
- 备库wal_receiver进程发送最新的wal lsn 给主库;
- 主库进行lsn 对比,定期向备库发送心跳信息,来确认备库的可用性,并且将没有传递的wal日志文件进行发送,同时调用SyncRepWaitForLSN()函数来获取锁存器,并且等待备库响应;锁存器的释放时机和主备同步模式的选择有关;
- 备库调用操作系统write()函数将wal文件写入缓存,然后调用操作系统fsync()函数将WAL刷新到磁盘,然后进行WAL文件回放;同时备库向主库返回ack确认信息,ack信息中包含write_lsn、flush_lsn、replay_lsn,用以告知主库当前的WAL日志在备库的应用位置以及状态,相关位置信息可以通过pg_stat_replication视图查看;
- 如果启用了hot_standby_feedback参数,备库会定期向主库发送xmin信息,用以保证主库不会vacuum掉备库需要的元组信息;
主:
# 修改配置文件 vim postgresql.conf wal_level = hot_standby # 修改WAL日志信息的输出级别 max_wal_senders = 10 # 设置最大的WAL发送进程数量,一个流复制的备库通常只消耗主库一个发送进程,必须小于max_connections wal_keep_segments = 512 # 设置WAL日志文件的保留数量,默认单个WAL文件的大小为16M,这里就是512*16MB=8GB logging_collector = on # 开启日志 log_directory = 'pg_log' # 设置日志路径 log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # 设置日志文件名 synchronous_commit = off # 关闭同步提交,只能为off,否则主库会一直等待备机响应,当备机故障时主机也会出现问题 # 创建复制用户 create user repl replication login password'123456'; # 修改用户认证文件 vim pg_hba.conf # 添加以下配置,考虑到主备角色互换,建议pg_hba.conf主备一样 host replication repl 192.168.10.128/32 md5 host replication repl 192.168.10.129/32 md5
从:
# 测试一下从服务器能否连接主服务器数据库 psql -U postgres -h 192.168.10.128 # 连接成功后停掉从库服务,清空从节点数据 rm -rf xxx/data/* # 从主节点拷贝数据到从节点 pg_basebackup -h 192.168.10.128 -U repl -D xxx/data -X stream -P # 复制share目录下的recovery.conf.sample文件,并修改recovery.conf cp $PGHOME/share/recovery.conf.sample $PGDATA/recovery.conf vim recovery.conf standby_mode = 'on' recovery_target_timeline = 'latest' primary_conninfo = 'host=192.168.10.128 port=5432 user=repl password=123456' # 注意修改备库配置文件,因为是从主库复制过来的 hot_standby = on #在备份的同时允许查询 max_standby_streaming_delay = 30s #可选,流复制最大延迟 wal_receiver_status_interval = 10s #可选,从向主报告状态的最大间隔时间 hot_standby_feedback = on #可选,查询冲突时向主反馈 max_connections = 1000 #默认参数,非主从配置相关参数,表示到数据库的连接数,一般从库做主要的读服务时,设置值需要高于主库 注意:data目录权限应是0700
主备切换:
停掉主库 pg_ctl promote 从库执行切换,执行后发现recovery.conf变为recovery.done文件 mv recovery.done recovery.conf 在原主库执行,修改其中的主库信息 启动原主库
同步模式:
PG提供了5种同步模式,由synchronous_commit参数控制;
- off:对于本机的WAL日志不用写入磁盘就可以提交,是异步模式,存在数据丢失风险;
- local:不管有没有备库,只需要保证本机的WAL日志刷到磁盘就行了;
- remote_write:等待主库日志刷新到磁盘,同时日志传递到备库的操作系统缓存中,不需要刷盘就能提交,不能避免操作系统崩溃;
- on:如果没有备库,则表示WAL日志需要刷新到磁盘中才能提交;如果存在同步备库(synchronous_standby_name不为空),则需要等待远程备库也刷新到磁盘,主库才能提交;
- remote_apply:PG高版本的功能,备库刷盘并且回放成功后,事务被标记为可见,用于做负载均衡,读写分离等;
- 主从切换流程
1.在A做checkpoint,三次 postgres=# checkpoint ; 2.修改A的pg_hba.conf并reload 注释下面一行 #host all all 0.0.0.1/0 md5 重新加载pg_hba.conf /data/postgres/pgsql/bin/pg_ctl reload -D /stage/data 3.在A上kill当前用户连接 postgres=# select pg_terminate_backend(pid) from pg_stat_activity where usename<>'postgres'; pg_terminate_backend ---------------------- (0 rows) 4、停止备机B、D 注释crontab /data/postgres/pgsql/bin/pg_ctl stop -D /stage/data 5.等待主备状态一致 执行几次checkpoint; select * from pg_stat_replication; 在原主建表插入数据验证一致性 create table tbase_test09(id int,dt date); INSERT INTO public.tbase_test09 VALUES (100,now()); #等待A和C上xlog一致,即最后一个xlog的md5sum的值完全一致,再进行第6步 6.停止主机A 注释crontab /data/postgres/pgsql/bin/pg_ctl stop -D /stage/data 7.提升C为主机 /data/postgres/pgsql/bin/pg_ctl promote -D /stage/data 查看是否能正常访问和读写是否正常