二、主從搭建 2.1測試目標 測試postgresql主從搭建安裝過程 2.2環境準備 實例級別的複製 流複製主庫可讀寫,但從庫只允許查詢不允許寫人, 而邏輯複製的從庫可讀寫 流複製實驗環境 主機 主機名 Ip地址 操作系統 Postgresql版本 主節點 pgsql 192.168.231.13 ...
二、主從搭建
2.1測試目標
測試postgresql主從搭建安裝過程
2.2環境準備
實例級別的複製
流複製主庫可讀寫,但從庫只允許查詢不允許寫人, 而邏輯複製的從庫可讀寫
流複製實驗環境
主機 |
主機名 |
Ip地址 |
操作系統 |
Postgresql版本 |
主節點 |
pgsql |
192.168.231.131 |
Redhat7.2 |
PostgreSQL10 |
備節點 |
pgstandby |
192.168.231.132 |
Redhat7.2 |
PostgreSQL10 |
在 pgsql 和 pgstandby上創建操作系統用戶和相關目錄,如下所示:
# groupadd pgsql
# useradd pgsql -g pgsql
# passwd pgsql
# mkdir -p /database/pg10/pg_root
# mkdir -p /database/pg10/pg_tbs
# chown -R pgsql:pgsql /database/pg10
/database/pg10/pg_root 目錄存儲資料庫系統數據文件,
/database/pg10/pg_tbs 存儲用戶自定義表空間文件。
設置 postgres 操作系統用戶環境變數,
/home/postgres/.bash _profile 文件添加以下內容:
export PGPORT=5432
export PGUSER=pgsql
export PGDATA=/database/pg10/pg_root
export LANG=en_US.utf8
export PGHOME=/usr/pgsql-10
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib
export PATH=$PGHOME/bin:$PATH:.
export MANPATH=$PGHOME/share/man:$MANPATH
2.3初始化資料庫
[pgsql@pgstandby ~]$ initdb -D /database/pg10/pg_root -E UTF8 --locale=C -U pgsql -W (初始化創建資料庫實例)
-A authmethod這個選項聲明本地用戶在 pg_hba.conf 裡面使用的認證方法。除非你相信所有本地用戶,否則不要使用 trust(預設)。
-D directory這個選項聲明資料庫集群應該存放在哪個目錄。這是 initdb 需要的唯一信息,但是你可以通過設置 PGDATA 環境變數來避免鍵入,這樣做可能方便一些,因為稍後資料庫伺服器(postgres)可以通過同一個變數找到資料庫目錄。
-E encoding 選擇模板資料庫的編碼方式。這將是你以後創建的資料庫的預設編碼方式,除非你創建資料庫時覆蓋了它。預設是從區域設置中獲得的,如果沒有區域設置,就是 SQL_ASCII 。
--locale=locale 為資料庫集群設置預設的區域。如果沒有聲明這個選項,那麼區域是從 initdb 運行的環境中繼承過來的。
-U username 選擇資料庫超級用戶的用戶名。預設是運行 initdb 的用戶的有效用戶。超級用戶的名字是什麼並不重要,但是可以選擇習慣的名字 postgres ,即使操作系統的用戶名字不一樣也沒關係。
-W 令 initdb 提示輸入資料庫超級用戶的口令。如果你不准備使用口令認證,這個東西並不重要。否則你將不能使用口令認證,直到你設置了口令。
--pwfile=filename令 initdb 從一個文件里讀取資料庫超級用戶的口令。該文件的第一行將被當作口令使用。
其它不常用的參數還有:
-d 從初始化後端列印調試輸出以及一些其它的一些普通用戶不太感興趣的信息。初始化後端是 initdb 用於創建系統表的程式。這個選項生成大量非常枯燥的輸出。
-L directory 告訴 initdb 到哪裡找初始化資料庫所需要的輸入文件。通常是不必要的。如果需要你明確聲明的話,程式會提示你輸入。
-n 預設時,當 initdb 發現一些錯誤妨礙它完成創建資料庫集群的工作時,它將在檢測到不能結束工作之前將其創建的所有文件刪除。這個選項禁止任何清理動作,因而對調試很有用。
之後配置 $PGDATA/postgresql.conf 設置以下參數:
listen_addresses = ‘*’
wal_level = replica # minimal, replica, or logical
archive_mode = on # enables archiving; off, on, or always
archive_command = ’/ bin/date’ # command to use to archive a logfile segment
max_wal_senders = 10 # max number of walsender processes
wal_keep_segments = 512 # in logfile segment s, 16MB each; 0 disables
hot_standby = on
listen_addresses參數指定哪些ip可以訪問,’*’代表所有ip可以訪問資料庫。
Wal_level參數控制WAL日誌信息的輸出級別,有minimal、replica、logical三種模式,minimal記錄的WAL日誌信息最少,除了記錄資料庫異常關閉需要恢復時的WAL信息外,其他操作信息都不記錄;replica記錄的WAL信息比minimal信息多些,會記錄支持WAL歸檔、複製和備庫中啟用只讀查詢等操作所需的WAL信息;logical記錄的WAL日誌信息最多,包含了支持邏輯解析(10版本的新特性,邏輯複製使用這種模式,本章後面會介紹)所需的WAL;replica模式記錄的WAL信息包含了minimal記錄的信息,logical模式記錄的WAL信息包含了replica記錄的信息,此參數預設值為replica,調整此參數需重啟資料庫生效,開啟流複製至少需要設置此參數為replica級別
Archive_mode參數控制是否啟用歸檔,off表示不啟用歸檔,on表示啟用歸檔並使用archive_command參數的配置命令將WAL日誌歸檔到歸檔存儲上,此參數設置後需重啟資料庫生效,這裡通常設置成on。
archive_command參數設置WAL歸檔命令,可以將WAL歸檔到本機目錄,也可以歸檔到遠程其他主機上,由於流複製的配置並不一定需要依賴配置歸檔命令,我們將歸檔命令暫且設置成偽歸檔命令/bin/date,後期如果需要打開歸檔直接配置歸檔命令即可。
max_wal_senders參數控制主庫上的最大WAL發送進程數,通過pg_base_backup命令在主庫上做基準備份時也會消耗WAL進程,此參數設置不能比max_connections參數值高,預設值為10,一個流複製備庫通常只需要消耗流複製主庫一個WAL發送進程。
wal_keep_segments參數設置主庫pg_wal目錄保留的最小WAL日誌文件數,以便備庫落後主庫時可以通過主庫保留的WAL進行追回,這個參數設置得越大,理論上備庫在異常斷開時追平主庫的機率越大,如果歸檔存儲空間充足,建議將此參數配置得大些,由於預設情況下每個WAL文件為16MB(編譯時可通過--with-walsegsize參數設置WAL文件大小),因此pg_wal目錄大概占用空間為wal_keep_segments參數值×16MB,這裡為512×16MB=8GB,實際情況下pg_wal目錄下的WAL文件數會比此參數的值稍大。
hot_standby參數控制資料庫恢復過程中是否啟用讀操作,這個參數通常用在流複製備庫,開啟此參數後流複製備庫支持只讀SQL,但備庫不支持寫操作,主庫上也設置此參數為on。
以上是流複製配置過程中主要的 postgresqI. conf參數,其他參數沒有列出,主庫和備庫的 postgresqI. conf配置建議完全一致。
配置主庫的pg_hba.conf文件,添加以下內容:
host replication repuser 192.168.231.131/24 md5
host replication repuser 192.168.231.132/24 md5
意思為允許repuser用戶從外部地址通過密碼連接任何資料庫,配置兩個信息是因為以後方便主備切換。
2.4 非同步流複製
2.4.1拷貝數據文件形式部署流複製(方案一)
# chown -R pgsql:pgsql /var/run/postgresql/ --若開啟postgresql資料庫失敗,報/var/run/postgresql/許可權不足的情況下,請賦權
drwxr-xr-x. 2 pgsql pgsql 80 Aug 9 11:03 postgresql
$ pg ctl start
使用超級用戶pgsql登錄到資料庫創建流複製用戶 repuser,流複製用戶需要有 REPLICATION 許可權和 LOGIN 許可權
[pgsql@pgsql ~]$ psql postgres
psql (10.9)
Type "help" for help.
postgres=# create user repuser replication login connection limit 5 encrypted password 'hufj123';
CREATE ROLE
postgres=# SELECT pg_start_backup('frans_bk1');
pg_start_backup
-----------------
0/2000028
(1 row)
pg_ start_ backup()函數在主庫上發起一個線上備份
[pgsql@pgsql pg10]$ tar czvf pg_root.tar.gz pg_root --exclude=pg_root/pg_wal --主庫將$PGDATA路徑下的東西進行備份,將pg_wal排除在外是因為,備庫會同步這些日誌
[pgsql@pgsql pg10]$ scp pg_root.tar.gz [email protected]:/database/pg10/ --將備份好的tar文件傳到備庫上去
備庫操作:
[pgsql@pgstandby pg10]$ tar xvf pg_root.tar.gz --備庫進行解壓,在$PGDATA目錄下
主庫操作:
[pgsql@pgsql pg10]$ psql postgres
postgres=# SELECT pg_stop_backup(); --主庫關閉備份,其實在備份好tar文件之後也可以進行關閉備份
NOTICE: pg_stop_backup complete, all required WAL segments have been archived
pg_stop_backup
----------------
0/2000130
(1 row)
[pgsql@pgstandby pg_root]$ cp /usr/pgsql-10/share/recovery.conf.sample $PGDATA/recovery.conf --備庫拷貝一份recovery.conf文件
[pgsql@pgstandby pg_root]$ vi recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.231.131 port=5432 user=repuser'
[pgsql@pgstandby ~]$ touch .pgpass --在家目錄下麵創建.pgpass文件,目的是在連接主庫的時候不需要輸入密碼
[pgsql@pgstandby ~]$ chmod 0600 .pgpass --註意賦予0600許可權
[pgsql@pgstandby ~]$ cat .pgpass
192.168.231.132:5432:replication:repuser:hufj123
192.168.231.131:5432:replication:repuser:hufj123
不配置 .pgpass文件則警告日誌顯示下麵信息
2019-08-05 11:37:42.556 CST [76967] FATAL: could not connect to the primary ser
ver: fe_sendauth: no password supplied
遇到錯誤查看日誌 $PGDATA/log/路徑的日誌。
如果此步沒報錯,並且主庫上可以查看到 WAL 發送進程,同時備庫上可以看到 WAL 接收進程說明流複製配置成功,查看主庫上的 WAL 發送進程, 如下所示:
[pgsql@pgsql ~]$ ps -ef|grep wal
pgsql 35001 34996 0 22:27 ? 00:00:00 postgres: wal writer process
pgsql 35006 34996 0 22:27 ? 00:00:00 postgres: wal sender process repuser 192.168.231.132(55152) streaming 0/7000098
pgsql 35008 34790 0 22:27 pts/1 00:00:00 grep --color=auto wal
查看備庫上的 WAL 接收進程,如下所示:
[pgsql@pgstandby ~]$ ps -ef|grep wal
pgsql 59336 59310 1 22:27 ? 00:00:00 postgres: wal receiver process streaming 0/70000D0
pgsql 59347 58742 0 22:27 pts/3 00:00:00 grep --color=auto wal
接著在主庫上創建一個測試表並插入數據,如下所示:
postgres=# create table test_sr(id int4);
CREATE TABLE
postgres=# insert into test_sr values(1);
INSERT 0 1
備庫上驗證數據是否同步:
postgres=# select * from test_sr;
id
----
1
(1 row)
2.4.2 pg_basebackup(實例級的備份) 方式部署流複製(方案二)
將備庫停庫,刪除資料庫,進行測試
[pgsql@pgstandby ~]$ pg_ctl stop
waiting for server to shut down.... done
server stopped
[pgsql@pgstandby ~]$ rm -rf /database/pg10/pg_root/*
[pgsql@pgstandby ~]$ rm -rf /database/pg10/pg_tbs/*
[pgsql@pgstandby ~]$ pg_basebackup -D /database/pg10/pg_root -Fp -Xs -v -P -h 192.168.231.131 -p 5432 -U repuser
-D 參數表示指定備節點用來接收主庫數據的目標路徑,這裡和主庫保持一致,依然是/database/pg10/pg_root目錄。
-F參數指定pg_basebackup命令生成的備份數據格式,支持兩種格式,p(plain)格式和t(tar)格式,p(plain)格式是指生成的備份數據和主庫上的數據文件佈局一樣,也就是說類似於操作系統命令將資料庫$PGDATA系統數據文件、表空間文件完全拷貝到備節點;t(tar)格式是指將備份文件打個tar包並存儲在指定目錄里,系統文件被打包成base.tar,其他表空間文件被打包成oid.tar,其中OID為表空間的OID。
-X參數設置在備份的過程中產生的WAL日誌包含在備份中的方式,有兩種可選方式,f(fetch)和s(stream),f(fetch)是指WAL日誌在基準備份完成後被傳送到備節點,這時主庫上的wal_keep_segments參數需要設置得較大,以免備份過程中產生的WAL還沒發送到備節點之前被主庫覆蓋掉,如果出現這種情況創建基準備份將會失敗,f(fetch)方式下主庫將會啟動一個基準備份WAL發送進程;s(stream)方式中主庫上除了啟動一個基準備份WAL發送進程外還會額外啟動一個WAL發送進程用於發送主庫產生的WAL增量日誌流,這種方式避免了f(fetch)方式過程中主庫的WAL被覆蓋掉的情況,生產環境流複製部署推薦這種方式,特別是比較繁忙的庫或者是大庫。
-v參數表示啟用verbose模式,命令執行過程中列印出各階段的日誌,建議啟用此參數,瞭解命令執行到哪個階段。
-P參數顯示數據文件、表空間文件近似傳輸百分比,由於執行pg_basebackup命令過程中主庫數據文件會變化,因此這隻是一個估算值;建議啟用此選項,瞭解數據複製的進度。
[pgsql@pgstandby~]$cp /usr/pgsql-10/share/recovery.conf.sample $PGDATA/recovery.conf --此文件在pghome/share/下麵
[pgsql@pgstandby ~]$ vi /database/pg10/pg_root/recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.231.131 port=5432 user=repuser'
[pgsql@pgstandby ~]$ pg_ctl start
postgres=# select usename,application_name,client_addr,sync_state from pg_stat_replication; --主庫查詢查看同步模式
usename | application_name | client_addr | sync_state
---------+------------------+-----------------+------------
repuser | walreceiver | 192.168.231.132 | async
2.5 同步流複製
非同步流複製指主庫上提交事務時不需要等待備庫接收井寫入WAL日誌時便返回成功,如果主庫異常看機,主庫上已提交的事務可能還沒來得及發送給備庫,就會造成備庫數據丟失,備庫丟失的數據量和WAL複製延遲有關,WAL複製延遲越大,備庫上丟失的數據量越大。同步流複製在主庫上提交事務時需等待備庫接收並WAL日誌,當主庫至少收到一個備庫發回的確認信息時便返回成功,同步流複製確保了至少一個備庫收到了主庫發送的WAL日誌,一方面保障了數據的完整性,另一方面增加了事務響應時間,因此同步流複製主庫的吞吐量相比非同步流複製主庫吞吐量低。
配置同步流複製
備庫recovery.conf配置文件設置以下參數,如下所示:
primary_conninfo=’host=192.168.231.131 port=5432 user=repuser application_name=node2’
primary_conninfo參數添加application_name選項,application_name選項指定備節點的別名,主庫postgresql.conf的synchronous_standby_names參數可引用備庫application_name選項設置的值,這裡設置成node2。
主庫上postgresql.conf配置文件設置以下參數,其他參數和非同步流複製配置一致。
synchronous_commit = on或remote_apply --建議設置為on,remote_apply是備庫應用後才返回信息
synchronous_standby_narnes = ’node2’
wal_level配置也和非同步流複製配置一致,設置成replica或logical即可。
重啟主庫與備庫查詢複製狀態為sync
[pgsql@pgsql pg_root]$ psql postgres
psql (10.9)
Type "help" for help.
postgres=# select usename,application_name ,client_addr ,sync_state from pg_stat_replication;
usename | application_name | client_addr | sync_state
---------+------------------+-----------------+------------
repuser | node2 | 192.168.231.132 | sync
(1 row)
postgres=#
流複製監控
pg_stat_replication視圖
application_name:連接WAL發送進程的應用別名,此參數顯示值為備庫recovery.conf配置文件中primary_conninfo參數application_name選項的值。
client_addr:連接到WAL發送進程的客戶端IP地址,也就是備庫的IP。
backend_start:WAL發送進程的啟動時間。
state:顯示WAL發送進程的狀態,startup表示WAL進程在啟動過程中;catchup表示備庫正在追趕主庫;streaming表示備庫已經追趕上了主庫,並且主庫向備庫發送WAL日誌流,這個狀態是流複製的常規狀態;backup表示通過pg_basebackup正在進行備份;stopping表示WAL發送進程正在關閉。
sent_lsn:WAL發送進程最近發送的WAL日誌位置。
write_lsn:備庫最近寫人的WAL日誌位置,這時WAL日誌流還在操作系統緩存中,還沒寫人備庫WAL日誌文件。
flush_lsn:備庫最近寫人的WAL日誌位置,這時WAL日誌流已寫入備庫WAL日誌文件。
replay_lsn:備庫最近應用的WAL日誌位置。
write_lag:主庫上WAL日誌落盤後等待備庫接收WAL日誌(這時WAL日誌流還沒寫人備庫WAL日誌文件,還在操作系統緩存中)並返回確認信息的時間。
flush_lag:主庫上WAL日誌落盤後等待備庫接收WAL日誌(這時WAL日誌流已寫人備庫WAL日誌文件,但還沒有應用WAL日誌)並返回確認信息的時間。
replay_lag:主庫上WAL日誌落盤後等待備庫接收WAL日誌(這時WAL日誌流已寫入備庫WAL日誌文件,並且己應用WAL日誌)並返回確認信息的時間。
sync_priority:基於優先順序的模式中備庫被選中成為同步備庫的優先順序,對於基於quorum的選舉模式此欄位則無影響。
sync_state:同步狀態,有以下狀態值,async表示備庫為非同步同步模式;potential表示備庫當前為非同步同步模式,如果當前的同步備庫岩機,非同步備庫可升級成為同步備庫;sync表示當前備庫為同步模式;quorum表示備庫為quorum standbys的候選。
pg_stat_wal_receiver顯示wal發送進程的詳細信息
主要欄位信息
pid:WAL接收進程的進程號。
status:WAL接收進程的狀態。
Receive_start_lsn:WAL接收進程啟動後使用的第一個WAL日誌位置。
Received_lsn:最近接收井寫人WAL日誌文件的WAL位置。
last_msg_send_time:備庫接收到發送進程最後一個消息後,向主庫發回確認消息的發送時間。
last_msg_receipt_time:備庫接收到發送進程最後一個消息的接收時間。
conninfo:WAL接收進程使用的連接串,連接信息由備庫$PGDATA目錄的recovery.conf配置文件的primary_conninfo參數配置。
三、流複製主備切換
3.1判斷主備角色
方式一:ps -ef|grep wal 查看wal進程描述信息,判斷主備
方式二: 主庫查詢SELECT * from pg_stat_replication,備庫查此視圖是無記錄的; 備庫查詢select * from pg_stat_wal_receiver,同主庫查此視圖無記錄。
方式三:SELECT pg_is_in_recovery(); 返回t說明為備庫,返回f為主庫。
方式四:通過pg_controldata查看資料庫控制信息;通過Database cluster state信息判斷;結果顯示 in production 為主庫;結果顯示 in archive recovery為備庫。
方式五:通過recover.conf配置文件查看。
3.2 判斷主備是否正常
(1) 查看主備庫的進程
主庫發送進程:
[pgsql@pgsql ~]$ ps -ef|grep wal
pgsql 35001 34996 0 22:27 ? 00:00:00 postgres: wal writer process
pgsql 35006 34996 0 22:27 ? 00:00:00 postgres: wal sender process repuser 192.168.231.132(55152) streaming 0/7000098
pgsql 35008 34790 0 22:27 pts/1 00:00:00 grep --color=auto wal
備庫為接收進程:
[pgsql@pgstandby ~]$ ps -ef|grep wal
pgsql 59336 59310 1 22:27 ? 00:00:00 postgres: wal receiver process streaming 0/70000D0
pgsql 59347 58742 0 22:27 pts/3 00:00:00 grep --color=auto wal
(2) 主庫插入數據,觀察備庫是否能收到數據。
(3) 主庫查詢複製狀態參數,是否正常。
[pgsql@pgsql pg_root]$ psql postgres
psql (10.9)
Type "help" for help.
postgres=# select usename,application_name ,client_addr ,sync_state from pg_stat_replication;
usename | application_name | client_addr | sync_state
---------+------------------+-----------------+------------
repuser | node2 | 192.168.231.132 | sync
(1 row)
3.3切換方式
通過觸發器文件方式觸發主備切換和通過pg_ctl promot命令觸發主備切換
一、 文件觸發方式
1) 配置備庫recovery.conf 文件的tigger_file參數,設置激活備庫的觸發文件路徑和名稱。添加tigger_file參數。
trigger_file = ‘/database/pg10/pg_root/.postgresql.trigger.5432’
2) 關閉主庫,使用 -m fast 模式關閉。(資料庫關閉時首先做一次checkpoint,wal進程會將截止此次checkpoint的wal日誌流發送給備庫,備庫在應用wal。)
3) 在備庫創建觸發文件激活備庫,當recovery.conf變為recovery.done表示備庫已切換為主庫。
[pgsql@pgstandby ~]$ cat /database/pg10/pg_root/recovery.conf |grep ^[^#]
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo='host=192.168.231.131 port=5432 user=repuser application_name=node2'
trigger_file='/database/pg10/pg_root/.postgresql.trigger.5432'
[pgsql@pgstandby ~]$ touch /database/pg10/pg_root/.postgresql.trigger.5432 --創建觸發文件,檢測不到主庫後會自動切換為主庫。
4) 在老主庫下創建recovery.conf文件,並配置相應參數,跟備庫的參數一樣。在根目錄下配置.pgpass免密文件。
[pgsql@pgstandby ~]$ vi /database/pg10/pg_root/recovery.conf --主要依據原來備庫的recovery.conf參數來進行設置。
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.231.131 port=5432 user=repuser'
[pgsql@pgstandby ~]$ cat .pgpass
192.168.231.132:5432:replication:repuser:hufj123
192.168.231.131:5432:replication:repuser:hufj123
5) 啟動老的主庫,觀察主備庫是否正常。
二、 主備切換之pg_ctl promote方式
pg_ctl promote [ D datadir]
-D 是指數據目錄,如果不指定會使用環境變數 $PGDATA 設置的值。 promote 命令發 出後,運行中的備庫將停止恢復模式並切換成讀寫模式的主庫。 pg_ctl promote 主備切換步驟和文件觸發方式大體相同。
1)關閉主庫,使用-m fast模式
2)備庫執行pg_ctl promote命令激活備庫
3)原主庫切換為備庫,創建recovery.conf文件,配置參數。
4)重新啟動原主庫,查看主備進程是否正常。
四、延遲備庫
配置參數 recovery_min_apply_delay(integer)單位支持天d,時h,分min,秒s,毫秒ms。
延遲操作主要是為了防止誤操作,而可以直接在備庫進行數據找回。參數recovery_min_apply_delay設置太大,會導致wal日誌占用更多空間,recovery_min_apply_delay參數設置太小,起不到數據恢復的用途。
recovery_min_apply_delay註意與參數synchronous_commit的復用。
若synchronous_commit=on;則無影響,只要備庫接受到日誌,主庫就可以不用等待延時參數的影響。若synchronous_commit=remote_apply,備庫需要接收到日誌,並延時應用wal日誌信息,那麼主庫就相應的會在延時後才收到備庫的消息,才能繼續下一事務。