PostgreSql基於Standby的異步流主從復制
PostgreSQl從9.0版本之後推出一個類似於Oracle的active dataguard和MySql中繼日誌一樣的日誌傳送。我們借助這個功能就可實現PostgreSql的主從復制。
基本原理就是,通常一臺主數據庫提供讀寫,然後把數據同步到另一臺從庫。從庫不斷apply從主庫接收到的數據,從庫不提供寫服務,只對外提供讀服務。在postgresql中提供讀寫全功能的服務器稱為primary database或master database,在接收主庫同步數據的同時又能提供讀服務的從庫服務器稱為hot standby server。
PostgreSQL在數據目錄下的pg_xlog子目錄中維護了一個
1. WAL日誌歸檔(base-file)
2. 流復制(streaming replication)
第一種是寫完一個WAL日誌後,才把WAL日誌文件拷貝到standby數據庫中,簡言之就是通過cp命令實現遠程備份,這樣通常備庫會落後主庫一個
在實際操作之前還有一點需要說明就是standby的搭建中最關鍵的一步——在standby中生成master的基礎備份。postgresql9.1之後提供了一個很方便的工具—— pg_basebackup,關於它的詳細介紹和參數說明可以在官網中查看(pg_basebackup tool),下面在搭建過程中再做相關具體說明。
二、基礎環境介紹
系統平臺:CentOS release 6.6 (Final)
Postgresql:postgresql-9.6.6
SELINUX=disabled
Iptables關閉
主庫(master)IP:192.168.221.161
從庫(standby)IP:192.168.221.160
基礎環境搭建可以參考前一篇文章(Centos6.6下Postgresql9.6.6安裝與配置),也就是PostgreSql的基本安裝與配置。
三、主庫配置
1. 在主庫增加同步的用戶名與密碼
[postgres@MidApp ~]$ psql psql (9.6.6) Type "help" for help. postgres=# CREATE ROLE repluser REPLICATION LOGIN PASSWORD '123456'; CREATE ROLE postgres=#
2. 修改/home/postgres/pgsql/data/pg_hba.conf,最後一行添加
[root@MidApp tmp]# tail -6 /home/postgres/pgsql/data/pg_hba.conf # Allow replication connections from localhost, by a user with the # replication privilege. #local replication postgres trust #host replication postgres 127.0.0.1/32 trust #host replication postgres ::1/128 trust Host replication repluser 192.168.221.160/32 md5
這行配置意思是允許用戶repluser從192.168.221.160這臺主機上以md5 加密的形式發起到本數據庫的流復制連接
3. 在主配置文件下配置下面幾個參數
listen_address = ‘*’(默認localhost) wal_level = hot_standby(默認是minimal) max_wal_senders=5(默認是0) wal_keep_segments=64(默認是0) synchronous_standby_names = 'standby01'
第一個參數表示監聽所有IP;第二個參數表示啟動hot standby;第三個參數表示主庫可以有多少個並發的standby數據庫,這裏設置為5;第四個參數表示一個WAL日誌文件大小,默認為16M
第五個參數指定同步復制的Standby名稱(從庫的recovery.conf中有要定義的地方,不過這一個參數可以不設置)
4. 重啟主庫,讓配置生效。
如果啟動有報錯,可以去日誌排查。
四、從庫配置
首先要保證主庫、從庫之間的同步之前的環境的是一致的,這樣才方便做同步。我因為之前就在從庫機器上配置過PG數據庫,所以一開始走了不少彎路。最後把PG的家目錄清空,重新再來一次才算成功。
1. 在從庫上通過pg_basebackup命令行工具生成基礎備份,命令如下,看到100%說明備份成功
[root@DB tmp]# pg_basebackup -h 192.168.221.161 -F p -P -D /home/postgres/pgsql/data -p5432 -U repluser --password Password: 22802/22802 kB (100%), 1/1 tablespace NOTICE: WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to comple
參數說明:-h 指定連接的數據庫IP;
-F 指定輸出的格式,支持p(plain原樣輸出)或者t(tar格式輸出)
-P 在備份過程中實時打印備份進度
-D 指定備份的目錄
-U 指定連接的用戶名
-p 指定要連接的端口
--password 指定要連接的用戶密碼
其他參數介紹:
-R 會在備份後自動生成recovery.conf文件,我也是事後才知道這個參數
-l 指定一個備份的標識
具體的參數介紹可以使用pg_basebackup --help查看,也可以查看官網介紹https://www.postgresql.org/docs/current/static/app-pgbasebackup.html
特別備註:我這裏沒有加-R參數,所以要手動拷貝一下recovery.conf
cp /home/postgres/pgsql/share/recovery.conf.sample /home/postgres/pgsql/data/recovery.conf
添加以下信息:
standby_mode = on primary_conninfo = 'application_name=standby01 user=repluser password=123456 host=192.168.221.161 port=5432 sslmode=disable sslcompression=1'
2. 修改從庫的主配置文件/home/postgres/pgsql/data/postgresql.conf
hot_standby = on
將hot_standby改為啟用狀態
3. 接下來可以啟動從庫了
[root@DB tmp]# /etc/init.d/postgresql start Starting PostgreSQL: -bash: /home/postgres/pgsql/data/serverlog: Permission denied ok
第一次啟動報錯,這是因為上面生成備份的命令我使用root用戶執行的,導致PG家目錄的屬性變成了root,所以要重新設置權限
chown -R postgres:postgres /home/postgres/pgsql/*
再次啟動正常,查看進程也OK
[root@DB tmp]# /etc/init.d/postgresql start Starting PostgreSQL: ok [root@DB tmp]# ps -ef | grep postg root 52577 82731 0 15:12 pts/0 00:00:00 su - postgres postgres 52578 52577 0 15:12 pts/0 00:00:00 -bash postgres 74295 1 0 20:01 ? 00:00:00 /home/postgres/pgsql/bin/postmaster -D /home/postgres/pgsql/data postgres 74296 74295 0 20:01 ? 00:00:00 postgres: startup process recovering 000000010000000000000003 postgres 74297 74295 5 20:01 ? 00:00:00 postgres: wal receiver process streaming 0/3000140 postgres 74298 74295 0 20:01 ? 00:00:00 postgres: checkpointer process postgres 74299 74295 0 20:01 ? 00:00:00 postgres: writer process postgres 74300 74295 0 20:01 ? 00:00:00 postgres: stats collector process
五、結果驗證
1. 在主庫通過select usename,application_name,client_addr,state from pg_stat_replication查詢一下:
[postgres@MidApp ~]$ psql psql (9.6.6) Type "help" for help. postgres=# select usename,application_name,client_addr,state from pg_stat_replication; usename | application_name | client_addr | state ----------+------------------+-----------------+----------- repluser | standby01 | 192.168.221.160 | streaming (1 row) postgres=#
可以看到192.168.221.160上的repluser在通過流復制的方式同步主庫的數據
2. 創建表驗證一下
主庫上建表,並插入數據驗證
postgres=# create table test01(id int primary key,note text); CREATE TABLE postgres=# \d List of relations Schema | Name | Type | Owner --------+--------+-------+---------- public | test01 | table | postgres (1 row) postgres=# insert into test01 values(1,'1111111'); INSERT 0 1 postgres=# select * from test01; id | note ----+--------- 1 | 1111111 (1 row)
在從庫上查看:
[postgres@DB data]$ psql psql (9.6.6) Type "help" for help. postgres=# \d List of relations Schema | Name | Type | Owner --------+--------+-------+---------- public | test01 | table | postgres (1 row) postgres=# select * from test01; id | note ----+--------- 1 | 1111111 (1 row)
嘗試插入數據看一下:
postgres=# insert into test01 values(2,'2222222'); ERROR: cannot execute INSERT in a read-only transaction
可以看到,從庫可以查看從主庫同步過來的數據,但並不能寫數據。
六、總結
以上是搭建Postgresql主從同步的全過程,一路踩了好多坑,記錄下了,希望能幫助到別人
PostgreSql基於Standby的異步流主從復制