PostgreSQL的流复制

文/Xie 2016-01-17 02:23:00

简介

本文介绍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,然后重启库就可以提供服务了。

总结

本文介绍了流复制的主、备库配置和主备同步测试,以及主库崩溃时备库如何提供服务。可见,流复制适合作为备份方案。

知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

最新文章 全部