一、簡介
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連接到主數據庫所需要的連接串。
7. 啟動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)
可以看到數據已經同步到了備庫,基本上感覺不到延遲。