PostgreSQL Hot-Standby
一、簡介
PostgreSQL資料庫提供了類似Oracle的standby資料庫的功能。PostgreSQL9.0 standby資料庫在應用WAL日誌的同時,也可以提供只讀服務,這是PostgreSQL9.0中最激動人心的功能,這個功能在oracle資料庫中也只是最新版本11g中才有的新功能。這個功能在oracle中叫active dataguard,在PostgreSQL中稱為hot standby。在利用日誌恢復資料的同時可以用只讀的方式開啟資料庫,使用者可以在備用資料庫上進行查詢、報表等操作,也可用做讀寫分離。在PostgreSQL9.0之前,也可以搭建standby資料庫,但standby資料庫只能處於恢復狀態中,不能開啟,也不支援只讀開啟。而這種情況在9.0之後徹底改變了。
PostgreSQL 9.0中日誌傳送的方法有兩種:
基於檔案(base-file)的傳送方式,這種方式是PostgreSQL9.0之前就提供的方法。也就是伺服器寫完一個WAL日誌檔案後,才把WAL日誌檔案拷貝到standby資料庫上去應用。
流複製(streaming replication)的方法,這是PostgreSQL9.0才提供的新方法。這個方法就是事務提交後,就會把生成的日誌非同步的傳送到standby資料庫上應用,這比基本檔案的日誌傳送方法有更低的資料延遲。
二、設定步驟
基於檔案(base-file)的傳送方式在PostgreSQL8.X中就有的方式,這裡不就介紹了,這裡主要介紹流複製的standby的搭建方法,設定步驟如下:
對主資料庫做一個基礎備份,然後把基礎備份拷貝到standby機器,把基礎備份恢復到standby機器上。
1、在主庫上設定wal_level = hot_standby。
2、在主資料庫上設定wal_keep_segments為一個足夠大的值,以防止主庫生成WAL日誌太快,日誌還沒有來得及傳送到standby,就會迴圈覆蓋了;
3、在主資料庫上設定max_wal_sender引數,這個引數是控制主庫可以最多有多少個併發的standby資料庫;
4、在主資料庫上建一個超級使用者,standby資料庫會使用這個使用者連線到主庫上拖WAL日誌。
5、在主資料庫上的pg_hba.conf中設定listen_addresses和連線驗證選項,允許standby資料庫連線到主庫上來拖WAL日誌資料,如下所示:
# TYPE DATABASE USER CIDR-ADDRESS METHOD
host replication postgres 10.0.0.136/8 md5
其中資料庫名必須填“replication”, 這是一個為standby連線使用了一個虛擬的資料庫名稱。使用者postgres就是步驟4上給standby連線使用的在主庫上建的一個超級使用者。10.0.0.136就是standby資料庫的IP地址。
6、在備份上建一個recovery.conf,設定以下幾項:
standby_mode = 'on'
primary_conninfo = 'host=127.0.0.1 port=5432 user=postgres password=123456'
trigger_file = '/opt/pgstb/trigger_standby'
standby_mode設定為'on',表明資料庫恢復完成後,不會被斷開,仍然處理等待日誌的模式。
primary_conninfo上standby連線到主資料庫所需要的連線串。
- 啟動standby資料庫,這樣standby資料庫就算搭建好了。
三、系統環境
系統平臺:Suse 11.4
PostgreSQL版本:9.0.3
四、例項分析
主資料庫:
Standby資料庫:
主資料庫的資料目錄為:/var/lib/pgsql/data,standby資料庫的資料目錄為/var/lib/pgsql/data。
在主資料庫的/var/lib/pgsql/data/postgresql.conf檔案中設定如下配置項:
wal_level = hot_standby
max_wal_senders = 2
wal_keep_segments = 32
在主資料庫中的/var/lib/pgsql/data/pg_hba.conf中新增如下配置:
host replication postgres 10.0.0.136/8 md5
在資料庫中建一個postgres使用者用於給standby連線主庫使用:
psql -d postgres
postgres=# create user postgres superuser password '123456';
CREATE ROLE
重新啟動主資料庫,讓配置生效:
對主資料庫做一個基礎備份:
先用select pg_start_backup();命令把資料庫切換到備份狀態。
把主資料庫目錄拷貝到備庫目錄就可以了:
檢視standby備庫目錄:
拷貝完成後,結束主庫的備份狀態:
修改備庫的配置檔案/var/lib/pgsql/data/postgresql.conf檔案中的相關項為如下內容:
hot_standby = on
把其中的hot_standby設定為on。
拷貝示例檔案/usr/share/postgresql/recovery.conf.sample到/var/lib/pgsql/data目錄下,然後改名成recovery.conf,修改相關的配置項為如下內容:
刪除原先從主庫上過來的/var/lib/pgsql/data/postmaster.pid檔案,然後啟動備庫:
複製程式碼
linux-david:/var/lib/pgsql/data # rm postmaster.pid
linux-david:/var/lib/pgsql/data # export PGDATA=/var/lib/pgsql/data
linux-david:/var/lib/pgsql/data # echo $PGDATA
/var/lib/pgsql/data
linux-david:/var/lib/pgsql/data # service postgresql start
server starting
linux-david:/var/lib/pgsql/data # LOG: database system was interrupted; last known up at 2010-08-21 22:43:04 CST
LOG: entering standby mode
LOG: redo starts at 0/1000020
LOG: record with zero length at 0/10000B0
LOG: streaming replication successfully connected to primary
LOG: consistent recovery state reached at 0/2000000
LOG: database system is ready to accept read only connections
複製程式碼
這時可以看到備庫已經可以接受只讀連線了。
在主庫上做一些操作:
複製程式碼
linux-david:/var/lib/pgsql/data # psql -p 5432 -d postgres
psql (9.0beta4)
Type "help" for help.
postgres=# create table t (id int primary key,name varchar(20));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_pkey" for table "t"
CREATE TABLE
postgres=# insert into t values (1,'xxxxxxx');
INSERT 0 1
postgres=# insert into t values (2,'xxxxxxx');
INSERT 0 1
postgres=#
複製程式碼
然後在備庫上看是否同步到了備庫:
複製程式碼
linux-david:/var/lib/pgsql/data # psql -p 5432 -d postgres
psql (9.0beta4)
Type "help" for help.
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | t | table | osdba
(1 row)
postgres=# select * from t;
id | name
----+---------
1 | xxxxxxx
2 | xxxxxxx
(2 rows)
複製程式碼
可以看到資料已經同步到了備庫,基本上感覺不到延遲。