目录
根据PostgreSQL异步流复制、同步流复制原理分析,同步流复制方式的事务响应时间比异步流复制方式的响应时间高,推测同步流复制的主库性能损耗比异步流复制要大些,实际情况如何呢?这一小节将通过一个读场景和一个写场景对单实例、异步流复制、同步流复制进行压力测试,使用的压力测试工具为pgbench,测试机配置为4逻辑核CPU、8GB内存的虚拟机。
单实例主库的postgresql.conf主要参数如下所示:
- wal_level = replica #minimal, replica, or logical
- synchronous_commit = off #synchronization level;
异步流复制主库的postgresql.conf主要参数如下所示:
- wal_level = replica # minimal, replica,or logical
- synchronous_commit = off # synchronization level;
- wal_keep_segments = 512 # in logfile segments, 16MB each; 0 disables
-
同步流复制主库的postgresql.conf主要参数如下所示:
- wal_level = replica # minimal, replica, or logical
- synchronous__commit = on # synchronization level;
- synchronous_standby_names = 'node2' # standby servers that provide sync rep wal_keep_segments = 512 # in logfile segments,16MB each; 0 disables
以上仅列出单实例、异步流复制、同步流复制模式的主要postgresql.conf参数,其他postgresql.conf参数配置一样。
先对单实例、异步流复制、同步流复制进行读性能对比,选择基于主键的查询场景进行读性能测试,创建测试表test_per1并插入1000万测试数据,如下所示:
- postgres=# CREATETABLE test_per1 (
- id int4,
- name text,
- create_time timestamp(0) without time zone default clock_timestamp( ) ) ;
- CREATETABLE
- postgres=# INSERTINTO test_per1 (id, name)
- SELECT n,n || 'per1'
- FROM generate_series ( 1 ,100000000) n;
- INSERT 0 10000000
之后添加主键并做表分析,如下所示。
- postgres=# ALTER TABLE test_perl ADD PRIMARY KEY(id);
- ALTERTABLE
- postgres=# ANALYZE test_per1;
- ANALYZE
编写压力测试查询SQL脚本,脚本名为select_per1.sql,如下所示:
- \set v_id random( 1,10000000)
- SELECT name FROM test_perl WHERE id= :v_id;
变量v_id从1到1000万范围内随机获取一个整数,根据主键查询表test _per1,之后测试并发连接数分别为2、4、8、16的TPS情况,pgbench测试脚本如下所示:
- pgbench -c 2 -T 120 -d postgres -U postgres -n N -M prepared -f select_per1.sql
- > select_2.out 2>&1 &
- pgbench -c 4 -T 120 -d postgres -U postgres -n N -M prepared -f elect_per1.sql
- > select_4.out 2>&1 &
- pgbench -c 8 -T 120 -d postgres -U postgres -n N -M prepared -f select_per1.sql
- > select_8.out 2>&1 &
- pgbench -c 16 T 120 -d postgres -U postgres -n N -M prepared -f select_per1.sql
- > select_16.out 2>&1 &
每次 pgbench测试时间为120秒,-M设置repared表示启用prepared statements,-n表示不做VACUUM操作,根据以上 pgbench测试脚本对单实例、异步流复制、同步流复制模式进行读压力测试,测试结果汇总如表所示。


从以上测试看出,并发连接数为4时性能最高,这与设备CPU核数有关,本测试虚机CPU逻辑核为4,并发连接数上升到8和16时,读性能降低。以上是根据主键查询的场景,在连接数小于4时,异步流复制和同步流复制比单实例读性能略有降低,降幅在5%以内,总体来说,单实例、异步流复制、同步流复制在基于主键的读场景下性能差异较小。
注意:测试过程中我们发现CPU使用率大部分情况都在50%以下,如果一个pgbench进程没有充分消耗虚拟机的所有计算资源,可以在系统上跑多个pgbench进程测试这台设备此查询场景的最高tps。
接着对单实例、异步流复制、同步流复制模式进行写性能测试,测试场景为基于主键的更新操作,创建测试表test_per2并插入1000万数据,如下所示:
- postgres=# CREATE TABLE test_per2(id int4, name text,flag char(1) ) ;
- CREATE TABLE
- postgres=# INSERT INTO test_per2 (id, name)
- SELECT n,n || 'per2'
- FROM generate_series( 1,10000000)n;
- INSERT 0 10000000
添加主键并做表分析,如下所示
- postgres=# ALTER TABLE test_per2 ADD PRIMARY KEY(id) ;
- ALTER TABLE
- postgres=# ANALYZE test_per2 ;
- ANALYZE
编写压力测试脚本,脚本名为update_per2.sql 如下所示:
- \set v_id random (1,1000000)
- update test_per2 set flag=' l' where id= : v_id;
变量v_id从1到1000万范围内随机获取一个整数,根据主键更新表test_per2的 flag字段,之后测试并发连接数分别为2、4、8、16的TPS情况,pgbench测试脚本如下所示:
- pgbench -c 2 -T 120 -d postgres -U postgres -n N -M prepared -f update_per2.sql
- > update_2.out 2>&1 &
- pgbench -c 4 -T 120 -d postgres -U postgres -n N -M prepared -f update_per2.sql
- > update_4.out 2>&1 &
- pgbench -c 8 -T 120 -d postgres -0 postgres -n N -M prepared -f pdate_per2.sql
- > update_8.out 2>&1 &
- pgbench -c 16 -T 120 -d postgres -U postgres -n N -M prepared -f update_per2.sql
- > update_16.out 2>&1 &
每次pgbench测试时间为120秒,根据以上pgbench测试脚本对单实例、异步流复制、同步流复制模式进行写压力测试,测试结果汇总如表所示。

从以上测试看出,基于主键更新的场景,异步流复制和单实例写性能几乎无差异,而同步流复制相比异步流复制和单实例场景性能大幅下降,在测试过程中,我们发现同步流复制主库上出现了大量UPDATE阻塞的情况,主要由于主库上提交事务时需等待备库接收并写入WAL日志后才向主库返回确认信息,这个过程消耗了大量通信时间,此过程消耗的时间越多,主库写场景TPS越小。