简介
本文介绍PostgreSQL数据库的流复制(stream replication)。流复制允许备库更新。备库连接主库,其产生的流WAL记录到备库。
在开始本文流复制的构建前,需要在两台机器上安装好PostgreSQL数据库,可以参考PostgreSQL基于源码的安装。其中备库的PostgreSQL可以先不执行initdb命令进行数据库初始化。另外,也可以在一台机器上启动两个PostgreSQL实例来搭建流复制环境。
我们所采用的环境是:
主库:美团云主机pg1,2CPU、2G内存、100G磁盘,IP为10.4.245.150
备库:美团云主机pg2,2CPU、2G内存、100G磁盘,IP为10.4.245.151
OS:CentOS 6.5
DB:PostgreSQL 9.3.5
配置主库
连接主库后,创建复制用户。
CREATE USER repuser REPLICATION LOGIN CONNECTION LIMIT 2 ENCRYPTED PASSWORD 'rep123us345er';
设置pg_hba.conf,添加以下内容。
host replication repuser 10.4.245.151/32 trust
设置主库postgresql.conf内容如下。
listen_addresses = '10.4.245.150' # 设置为内网IP,允许远程登录主机
wal_level = hot_standby # write ahead log,流复制时为hot_standby
hot_standby = on
max_wal_senders = 2 # 流复制的最大连接数
wal_keep_segments = 16 # 流复制保留的最大xlog数
重启数据库。
pg_ctl restart
查看表空间目录和数据目录。
[postgres@pg1 data]$ psql
psql (9.3.5)
Type "help" for help.
postgres=# \db
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |
(2 rows)
postgres=# \q
[postgres@pg1 data]$ echo $PGDATA
/opt/PostgreSQL/9.3.5/data
先查看表空间目录和数据目录,是因为这些目录需要在备库主机上手工创建。
配置备库
创建目录并授权。需要确认备库是否有与主库相同的数据目录,如果有,需要先移除。
cd /opt/PostgreSQL/9.3.5/
mv data data20151116
mkdir -p /opt/PostgreSQL/9.3.5/data
chown -R postgres /opt/PostgreSQL/9.3.5/data
chmod 700 /opt/PostgreSQL/9.3.5/data
在postgres根目录下创建.pgpass,加入如下内容。
10.4.245.150:5432:postgres:repuser:rep123us345er
执行如下命令进行授权。
chmod 600 ~/.pgpass
使用pg_backendup生成备库。
su postgres
pg_basebackup -D /opt/PostgreSQL/9.3.5/data -Fp -Xs -v -P -h 10.4.245.150 -p 5432 -U repuser
这时表空间目录和$PGDATA目录已经复制过来了。本文的环境中没有额外的表空间目录。
设置备库recovery.conf。首先执行如下命令生成recovery.conf文件。
cp /opt/PostgreSQL/9.3.5/share/postgresql/recovery.conf.sample $PGDATA/recovery.conf
然后在recovery.conf中添加如下内容。其中,需要确保postgres用户对/data/pgsql目录具有写权限。
standby_mode = 'on'
trigger_file = '/data/pgsql/pg.trigger'
primary_conninfo = ‘host=10.4.245.150 port=5432 user=repuser password=rep123us345er'
启动备库服务。
pg_ctl start
测试主备同步
执行如下命令查看备库进程中有”postgres: wal receiver process”,确认主库中进程有“postgres: wal sender process”。
ps -ef | grep postgres
进入测试数据库testdb,主库上执行如下命令返回f,备库上返回t。
select pg_is_in_recovery();
执行如下命令查看快照,它返回主库记录点、备库记录点;主库每增加一条写入,记录点的值就会加1。
testdb=# select txid_current_snapshot();
txid_current_snapshot
-----------------------
1820:1820:
(1 row)
testdb=# insert into ta values(now());
INSERT 0 1
testdb=# select txid_current_snapshot();
txid_current_snapshot
-----------------------
1821:1821:
(1 row)
执行如下命令可以查看主备同步状态。
select * from pg_stat_replication;
字段state显示的同步状态有:startup(连接中)、catchup(同步中)、streaming(同步);字段sync_state显示的模式有:async(异步)、sync(同步)、potential(虽然现在是异步模式,但是有可能升级到同步模式)。
在主库中添加测试数据。
testdb=# create table tb (id int4, create_time timestamp(0) without time zone);
CREATE TABLE
testdb=# insert into tb values (1, now());
INSERT 0 1
testdb=# select * from tb;
id | create_time
----+---------------------
1 | 2015-11-16 20:51:13
在备库查看数据。
testdb=# select * from tb;
id | create_time
----+---------------------
1 | 2015-11-16 20:51:13
(1 row)
testdb=# insert into tb values (1, now());
ERROR: cannot execute INSERT in a read-only transaction
STATEMENT: insert into tb values (1, now());
备库上执行insert语句会报错,因为备库是只读的。
主备切换
假设主库崩溃了,备库如何从只读状态切换为读写状态呢?只要把备库的postgresql.conf中hot_standby修改为off,并且删除recovery.conf,然后重启库就可以提供服务了。
总结
本文介绍了流复制的主、备库配置和主备同步测试,以及主库崩溃时备库如何提供服务。可见,流复制适合作为备份方案。