都说数据无价,本文就介绍一下如何快速拥有一个PostgreSQL的备库,从而实现主从数据库。通常情况下,从库可以作为一个备份的存在(只读),当主库出现宕机后,我们可以快速把从库提升为主库(读写)。步骤并不复杂,一起来尝试一下吧。

创建用户,专门用来实现数据复制

create user replica with replication login password 'replication';

检查postgresql.conf配置文件

wal_level = replica

检查pg_hba.conf权限配置文件

建议在最后追加一行host replication replica all md5,其中all也可以替换为从库所处机器的ip地址,比如192.168.0.10/32

生成备份库

 pg_basebackup -h 192.168.0.21 -p 54321 -U replica -R -P -v -C --slot=pgstandby1 -D /Users/liurui/pg2
  • -R 说明会创建standby.signal文件,以及补充postgresql.auto.conf的内容
  • -P 显示备份进度
  • -v 显示更加详细信息
  • -C 同时创建复制槽
  • --slot 指定复制槽的名字(一个备库一个名字)
  • -D 生成备库的路径

复制槽的好处
主库的事务日志一直处于滚动消耗的状态,如果备库下线,随着主库频繁的数据变动,可能就会存在当备库重新上线后,已经找不到之前没有拉取的事务日志的情况(被主库回收掉了)。
但是有了复制槽,主库就会为复制槽保留它没有消费的日志,等待它上线后进行消费。当然代价是对磁盘的消耗,不过只要备库不是永久丢失,磁盘消耗对于大部分场景来说不是问题。
但是如果备库永久丢失了,要记得删除主库中对应的复制槽。删除复制槽的语句为select pg_drop_replication_slot('pgstandby1');

注意
备库的操作系统环境最好与主库一致,如果一个是Windows一个是Linux,几乎一定会遇到字符集不一致的问题,导致备库无法启动。

启动备库

pg_ctl -D /Users/liurui/pg2 start

验证流复制可用性

  • 在主库进行数据变动,在备库可进行观察
  • 在主库执行select * from pg_replication_slots;能够观察到复制槽
  • 在主库执行select * from pg_stat_replication;可以观察到备库连接情况,只有备库上线的情况下,该查询才会返回数据
  • 顺便说一下,从库的数据目录会生成名为postgresql.auto.conf的文件(对应上面的-R参数),里面存放了主库的连接信息,感兴趣的小伙伴可以观察看看,但是这个文件不建议手动编辑。
  • 注意,这样创建的备库其实叫异步备库,极端情况下,备库的数据跟主库比是有一定延迟的,如果需要无延迟的备库,就需要启动同步模式,当然它会牺牲更多的性能,也要付出更高的运维成本,本文并不涉及同步模式的介绍。

如何获得指定延迟时间的备库(可选)

大部分情况下,备库与主库保持一致是我们需要的。但是有时候,我们也需要的也一个比主库有延迟的备库,比如延迟三十分钟,也就意味着,当主库的数据被不小心删除后,三十分钟内,我们都可以在备库里找到。此时需要在备库配置:

recovery_min_apply_delay = 30min

手动把备库提升为主库

备库平时只能作为只读数据库使用,因为可写数据是主库才有的特权。但是一旦主库挂掉,并且已知备库的数据足够完整的情况下,我们可以迅速把备库提升为主库。只要找到备库的文件路径,把里面的standby.signal文件删除即可。顺便说一下,这个文件是没有内容的,它是一个空文件,通过这个文件的存在来表明自己是个备库,所以删掉或者重命名该文件,都能把这个备库提升为主库。当然,别忘了删除该文件后,重启备库才能生效。

补充:在docker环境下生成备库

  1. 像平常在docker使用一样,启动一个数据库,当然要注意该备库的版本与主库保持一致。一个典型的yml文件如下:

    version: '3'
    services:
     postgres15-bak:
      image: postgres:15.1
      ports:
       - 34325:5432
      volumes:
       - /root/docker/volume/postgres15:/var/lib/postgresql/data
    
  2. 使用docker-compose启动该镜像后,再通过docker exec进入它

  3. 切换用户:su postgres

  4. 进入postgres拥有权限的路径:cd /var/lib/postgresql/data

  5. 生成备库:pg_basebackup -h 192.168.0.21 -p 54321 -U replica -R -P -v -C --slot=pgstandby1 -D ./bak 此时备库路径就在/var/lib/postgresql/data/bak

  6. 退出docker,回到宿主机,并关闭刚刚使用的docker镜像

  7. 在宿主机把刚才镜像映射的文件夹调整一下,以上面的yml文件为例,就应该先把/root/docker/volume/postgres15/bak文件夹拷贝出来,再把/root/docker/volume/postgres15文件夹删除掉,之后把刚拷贝出来的bak文件夹还原为/root/docker/volume/postgres15,此时该镜像映射的文件夹就是我们新产生的从库备份了。

  8. 启动上面的docker镜像。则从库已经接入主库。