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支持两种方式来进行编译:
在gogudb的目录下执行安装gogudb:
sudo make install
在当前PG的实例的配置文件中增加:
shared_preload_libraries='gogudb'
这个配置项需要数据重启才能生效。
使用有相应权限的用户执行:
create externsion gogudb
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 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会根据改变预先定义的规则,来创建分区表。该表主要包括下列字段:
gogudb中有一张表 server_map(1.0版本在pg_catalog这个schema下,而1.1移到了_gogu这个schema下)定义了做hash值的范围和远程数据源的关系,这张表主要有下面三个字段:
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的远程数据源。
编辑gogu01机器上(即gogudb)数据库的配置文件: vi /data/pgdata/postgresql.conf 在配置文件中增加一行:
shared_preload_libraries='gogudb'
使用前面描述的方法,编译gogudb之后使用make install安装
启动gogudb数据库:
pg_ctl start -D /data/pgdata
需要在gogudb的数据库中创建gogudb的extension
create extension gogudb;
创建两个数据源,分别指向拍pg01和pg02:
执行下列操作:
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)。
主要是先在table_partition_rule中插入表的分区规则,然后使用普通SQL来创建表。
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_testTable "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_testpostgres=# \dES gogudb_partition_table.*List of relationsSchema | Name | Type | Owner------------------------+------------------------+---------------+-------gogudb_partition_table | _public_0_part_hash_test | foreign table | pgsqlgogudb_partition_table | _public_1_part_hash_test | foreign table | pgsqlgogudb_partition_table | _public_2_part_hash_test | foreign table | pgsqlgogudb_partition_table | _public_3_part_hash_test | foreign table | pgsql
*删除表:
postgres=# drop table part_hash_test cascade;NOTICE: drop cascades to 4 other objectsDETAIL: drop cascades to foreign table gogudb_partition_table._public_0_part_hash_testdrop cascades to foreign table gogudb_partition_table._public_1_part_hash_testdrop cascades to foreign table gogudb_partition_table._public_2_part_hash_testdrop cascades to foreign table gogudb_partition_table._public_3_part_hash_testDROP TABLE
主要的步骤也是先向配置表中插入数据,然后使用普通的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 00
0’,会创建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_testpostgres=# \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;