简介
gogudb是一个基于FDW技术的分库分表中间件,主要采用了分区管理技术(pg_pathman)和外部数据源(postgres_fdw)的技术。支持以extension的方式加载到PG数据库上运行,支持以透明的方式访问其他PG数据库上的表。支持常见的SQL操作,支持触发器,支持跨节点的连接、排序、聚集操作等。
代码目前公开在github上面:https://github.com/hangzhou-cstech/gogudb
gogudb支持 PG9.6 10 11,支持X86_64的操作系统。
编译
目前,gogudb支持两种方式来进行编译:
- 一种是使用PG源码的方式来进行安装,
- 一种是使用安装之后的PG来进行编译,安装PG的方式不限,但是需要设置环境变量,使得在在shell中能直接使用pg_config来获取PG的相关文件路径。
gogudb在PG源码下进行编译
- 下载PG源码(9.6 10 11版本),使用tar解压缩
- 使用configure进行配置,生成makefile
- 使用git将代码获取,放置到contrib下的gogudb目录下面
- 在gogudb的目录下面,执行make,即可获得gogudb的动态库文件和sql文件,完成使用版的编译。
gogudb在安装PG之后进行编译
- 安装PG,可以使用源码安装或是使用yum或是rpm来进行安装,PG的版本同上。注意设置环境变量,使得shell中可以直接使用pg_config
- 使用git获取gogudb源码
- 在gogudb的源码目录下执行make USE_PGXS=1命令来编译,获得使用版的动态库文件和sql文件。
安装
在gogudb的目录下执行安装gogudb:
sudo make install
配置
在当前PG的实例的配置文件中增加:
shared_preload_libraries='gogudb'
这个配置项需要数据重启才能生效。
使用
创建 extension
使用有相应权限的用户执行:
create externsion gogudb
创建数据源
- 使用create server语句创建数据源,例如:
CREATE SERVER server_remote1 FOREIGN DATA WRAPPER gogudb_fdw OPTIONS(host '192.168.2.2',port '5432',dbname 'postgres');
创建了一个名为server_remote1的数据源,远程数据源的IP是192.168.2.2,端口是5432,数据库名是postgres,使用的是gogudb内置的fdw:gogudb_fdw
- 使用create user mapping语句来配置数据源的访问用户信息,例如:
create user mapping for current_user server server_remote1 options(user 'pgsql',password '');
设置当前用户访问server_remote1时,使用的登录用户是pgsql,密码为空。
配置表的分表规则
gogudb中有一张表 table_partition_rule(1.0版本在pg_catalog这个schema下,而1.1移到了_gogu这个schema下)定义了用户分表的规则,在创建分区表之前,用户需要在表中插入数据。在创建表的时候,gogudb会根据改变预先定义的规则,来创建分区表。该表主要包括下列字段:
- schema_name 类型TEXT NOT NULL,指定即将创建的父表所在的schema
- table_name 类型TEXT NOT NULL,指定即将创建的父表的名称,
- part_expr 类型TEXTTEXT NOT NULL,指定分表时使用的表达式(最简单的就是列名)
- part_type 类型INTEGER NOT NULL,分区类型,只能选择1或是2,1表示hash分区,2表示range分区
- range_interval 类型TEXT DEFAULT NULL, range分区时使用的间隔。
- range_start 类型TEXT DEFAULT NULL,range分区时使用起始值。
- part_dist 类型INTEGER,子表的总数量,最终创建远程子表时,子表会逐一分布到每个远程数据源上数量,尽量保证每个数据源上的子表数据量均匀一致。
- remote_schema 类型 TEXT DEFAULT NULL,子表在远程数据源上的schema,默认为public
- servers 类型TEXT[] DEFAULT NULL,子表分布的远程数据源名称列表,默认是系统内所有使用gogudb_fdw的远程的数据源列表。
配置远程数据源的HASH值区间
gogudb中有一张表 server_map(1.0版本在pg_catalog这个schema下,而1.1移到了_gogu这个schema下)定义了做hash值的范围和远程数据源的关系,这张表主要有下面三个字段:
- server_name, TEXT NOT NULL类型,子表分布的远程数据源名称列表,默认是系统内所有使用gogudb_fdw的远程的数据源列表。
- range_start,smallint NOT NULL类型,hash值范围的起始值(包括该值),最小为0;
- range_end,smallint NOT NULL类型,hash值范围的结束值(不包括该值),不小于range_start,不大于128;
用户向 pg_catalog.server_map插入数据源以及范围之后,需要执行
select reload_range_server_set()
来重新加载server_map表的数据,使之生效。
使用案例
准备测试环境的数据库实例
环境如下:
主机名 | IP | 数据库端口 | 数据目录 |
---|---|---|---|
gogu01 | 192.168.3.46 | 5432 | /home/postgres/pgdata |
pg01 | 192.168.3.41 | 5432 | /home/postgres/pgdata |
pg02 | 192.168.3.42 | 5432 | /home/postgres/pgdata |
其中gogu01作为gogudb的运行实例,pg01和pg02作为gogudb的远程数据源。
配置gogudb
编辑gogu01机器上(即gogudb)数据库的配置文件: vi /data/pgdata/postgresql.conf 在配置文件中增加一行:
shared_preload_libraries='gogudb'
安装gogudb
使用前面描述的方法,编译gogudb之后使用make install安装
启动数据库:
启动gogudb数据库:
pg_ctl start -D /data/pgdata
创建extension
需要在gogudb的数据库中创建gogudb的extension
- 连接gogudb数据库:
psql -d postgres - 在连接会话中创建gogudb:
create extension gogudb;
创建远程数据源
创建两个数据源,分别指向拍pg01和pg02:
- 连接gogudb数据库: psql -d postgres
- 创建名为server_remote1的数据源:CREATE SERVER server_remote1 FOREIGN DATA WRAPPER gogudb_fdw OPTIONS(host ‘192.168.3.41’,port ‘5432’,dbname ‘postgres’);
- 创建名为server_remote2的数据源:CREATE SERVER server_remote2 FOREIGN DATA WRAPPER gogudb_fdw OPTIONS(host ‘192.168.3.42’,port ‘5432’,dbname ‘postgres’);
- 为server_remote1设置用户名密码:create user mapping for current_user server server_remote1 options(user ‘pgsql’,password ‘’);
- 为server_remote2设置用户名密码:create user mapping for current_user server server_remote1 options(user ‘pgsql’,password ‘’);
配置远程数据源的hash值分区
执行下列操作:
insert into _gogu.server_map values('server_remote1', 0, 64), ('server_remote2', 64, 128);
select reload_range_server_set();
这就配置并生效了两台远程数据源server_remote1和server_remote2,server_remote1接受的hash值范围是[0,64), server_remote2接受的范围是[64,128)。
使用hash方式创建分区表
主要是先在table_partition_rule中插入表的分区规则,然后使用普通SQL来创建表。
- 连接gogudb数据库: psql -d postgres
- 插入分区规则:
insert into _gogu.table_partition_rule(schema_name, table_name, part_expr, part_type, part_dist, remote_schema) values('public', 'part_hash_test', 'id', 1,4,'public');
插入的记录指定了:将会在public的schema下创建一张表,表的分布字段是id,采用hash分区,总共4个分片,分片将分布到所有的gogudb_fdw的远程的数据源列表上,所在的schema为public
- 创建分区表:
postgres=# CREATE TABLE part_hash_test(id INT NOT NULL, payload REAL);
CREATE TABLE
*可以查看生成的分区表:
postgres=# \d+ part_hash_test
Table "public.part_hash_test"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------+---------+-----------+----------+---------+---------+--------------+-------------
id | integer | | not null | | plain | |
payload | real | | | | plain | |
Child tables: gogudb_partition_table._public_0_part_hash_test,
gogudb_partition_table._public_1_part_hash_test,
gogudb_partition_table._public_2_part_hash_test,
gogudb_partition_table._public_3_part_hash_test
postgres=# \dES gogudb_partition_table.*
List of relations
Schema | Name | Type | Owner
------------------------+------------------------+---------------+-------
gogudb_partition_table | _public_0_part_hash_test | foreign table | pgsql
gogudb_partition_table | _public_1_part_hash_test | foreign table | pgsql
gogudb_partition_table | _public_2_part_hash_test | foreign table | pgsql
gogudb_partition_table | _public_3_part_hash_test | foreign table | pgsql
*删除表:
postgres=# drop table part_hash_test cascade;
NOTICE: drop cascades to 4 other objects
DETAIL: drop cascades to foreign table gogudb_partition_table._public_0_part_hash_test
drop cascades to foreign table gogudb_partition_table._public_1_part_hash_test
drop cascades to foreign table gogudb_partition_table._public_2_part_hash_test
drop cascades to foreign table gogudb_partition_table._public_3_part_hash_test
DROP TABLE
使用range方式创建基于时间类型分区表
主要的步骤也是先向配置表中插入数据,然后使用普通的SQL来建表。
- 向分区配置表插入数据:
insert into _gogu.table_partition_rule(schema_name ,table_name ,part_expr ,part_type ,range_interval ,range_start ,part_dist, remote_schema) values('public', 'part_range_test', 'crt_time', 2, '2 month','2018-1-1 000', 6, 'public');
这个指定即将创建表的schema是pulic,表名是part_range_test,分表会使用的表达式是’crt_time,实际将会是一个timestamp类型的字段,分区的类型是range方式,分区间隔是’2 month’,起始值是’2018-1-1 000’,会创建6个分片,分片位于所有数据源上,schema为public。
*创建表:
postgres=# create table part_range_test(id int, info text, crt_time timestamp not null);
CREATE TABLE
*可以查看这个表由6个子表组成,实际是外部表,均分到2个外部数据源上:
postgres=# \d+ part_range_test
Table "public.part_range_test"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+---------+----------+--------------+-------------
id | integer | | | | plain | |
info | text | | | | extended | |
crt_time | timestamp without time zone | | not null | | plain | |
Child tables: gogudb_partition_table._public_1_part_range_test,
gogudb_partition_table._public_2_part_range_test,
gogudb_partition_table._public_3_part_range_test,
gogudb_partition_table._public_4_part_range_test,
gogudb_partition_table._public_5_part_range_test,
gogudb_partition_table._public_6_part_range_test
postgres=# \dES gogudb_partition_table.*
List of relations
Schema | Name | Type | Owner
------------------------+-------------------------+---------------+-------
gogudb_partition_table | _public_1_part_range_test | foreign table | pgsql
gogudb_partition_table | _public_2_part_range_test | foreign table | pgsql
gogudb_partition_table | _public_3_part_range_test | foreign table | pgsql
gogudb_partition_table | _public_4_part_range_test | foreign table | pgsql
gogudb_partition_table | _public_5_part_range_test | foreign table | pgsql
gogudb_partition_table | _public_6_part_range_test | foreign table | pgsql
(6 rows)
*使用普通SQL来删除表:
postgres=# drop table part_range_test;
DROP TABLE
使用range方式创建基于数值类型分区表
- 向分区配置表插入数据:
insert into _gogu.table_partition_rule(schema_name, table_name, part_expr, part_type, part_dist, remote_schema, range_interval,range_start) values('public','part_range_num_test', 'id', 2, 4, 'public', '100', '0');
注意对于1.0版本,上面的函数和表名前不需要加“_gogu.”
指定即将创建表的schema是pulic,表名是part_range_num_test,分表会使用的表达式是id,实际将会是一个int类型的字段,分区的类型是range方式,分区间隔是’100’,起始值是’0’,会创建4个分片,分片位于所有数据源上,schema为public。
- 创建表:
postgres=# CREATE TABLE part_range_num_test ( id integer NOT NULL, k integer DEFAULT 0 NOT NULL);、;
CREATE TABLE
- 可以查看这个表由4个子表组成:
postgres=# \d+ part_range_num_test
Table "public.part_range_num_test"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
id | integer | | not null | | plain | |
k | integer | | not null | 0 | plain | |
Child tables: gogudb_partition_table._public_1_part_range_num_test,
gogudb_partition_table._public_2_part_range_num_test,
gogudb_partition_table._public_3_part_range_num_test,
gogudb_partition_table._public_4_part_range_num_test
- 删除表
postgres=# drop table part_range_num_test cascade;
drop table part_hash_test;