PostgreSQL sharding for Oracle, SQL Server, DB2, Sybase

Oracle 12c支持sharding,但是对于低版本,如何实现水平分库呢?
在写PostgreSQL 水平分库方案时,想到一招。何不利用PostgreSQL的分片技术来实现对Oracle的分片呢?
分库技术架构和实践请参考:
http://blog.163.com/digoal@126/blog/static/16387704020161239252998/

如果要做到对Oracle用户完全透明,需要满足几个条件:
1. PostgreSQL必须支持Oracle的SQL语法,这一点 EnterpriseDB 可以满足需求。
2. PostgreSQL必须支持Oracle的存储过程和函数,以及包。这一点 EnterpriseDB 可以满足需求。
如果用户愿意修改不兼容的SQL和函数,使用社区版本的 PostgreSQL 就能满足分片需求了。

分片架构如下:
可以支持几乎任何数据库的分片。

分为两层:
1. 上层为PostgreSQL 或 EnterpriseDB(如果需要兼容Oracle特殊语法),在上层节点中,需要存储表的定义,路由算法,函数,存储过程,视图,序列等全局数据。
上层的PostgreSQL数据库可以有1个或者多个,最少1个。
2. 下层为数据分片节点,可以是任何数据库品种,譬如图中所述的Oracle, DB2, Sybase, SQL Server。在分片节点中,存储数据分片,维度表(用户可以自定义维度表的副本数)。

注意,如果要支持函数,必须将原数据库的函数转换为PostgreSQL的函数,在PostgreSQL中可以使用plpgsql语言来实现,包括自治事务也能实现
(参考 http://blog.163.com/digoal@126/blog/static/163877040201613982063/ )。
如果使用EnterpriseDB,则大多数的Oracle函数语法都兼容,用户可以不需要修改,直接使用。

以Oracle为例,介绍实施步骤:
.1. 安装Oracle数据节点,这里假设有4台Oracle数据库,分别为db0,db1,db2,db3。
.2. 安装一台PostgreSQL 9.5+ 以及 oracle_fdw插件。
插件位置:http://pgxn.org/dist/oracle_fdw/
内含详细说明,推荐阅读。
http://blog.163.com/digoal@126/blog/static/163877040201181505331588/
安装好后,设置正确的 NLS_LANG 环境变量(_. (for example AMERICAN_AMERICA.AL32UTF8)),重启数据库。
.3. 配置oracle数据库监听,以及主机防火墙,允许PostgreSQL数据库访问Oracle数据库。
.4. 在PostgreSQL数据库中创建所有数据节点的foreign server, 本例需要4个foreign server, user mapping。
例如 (请使用正确的 IP,端口和sid, username, password替换) :

master=# create extension oracle_fdw;
master=# create server db0 foreign data wrapper oracle_fdw OPTIONS (dbserver '//ip:port/sid');
master=# create server db0 foreign data wrapper oracle_fdw OPTIONS (dbserver '//ip:port/sid');
master=# create server db0 foreign data wrapper oracle_fdw OPTIONS (dbserver '//ip:port/sid');
master=# create server db0 foreign data wrapper oracle_fdw OPTIONS (dbserver '//ip:port/sid');
master=# create user mapping for postgres server db0 options (user 'username', password 'pwd');
master=# create user mapping for postgres server db1 options (user 'username', password 'pwd');
master=# create user mapping for postgres server db2 options (user 'username', password 'pwd');
master=# create user mapping for postgres server db3 options (user 'username', password 'pwd');

.5. 规划表分区的分布列,如果分布列不是INT类型,可以使用hash函数转换为INT。按abs(mod(column,4))的值计算分布规则。
.6. 在所有的数据节点db[0-3],创建需要分片的表,以及分布列的 check 约束。
例如:

on db0:
create table tbl ( id int primary key , info varchar2(32), crt_time date, check (abs(mod(id,4))=0));
on db1:
create table tbl ( id int primary key , info varchar2(32), crt_time date, check (abs(mod(id,4))=1));
on db2:
create table tbl ( id int primary key , info varchar2(32), crt_time date, check (abs(mod(id,4))=2));
on db3:
create table tbl ( id int primary key , info varchar2(32), crt_time date, check (abs(mod(id,4))=3));

.7. 规划维度表的副本数,本文例子假设维度表有2个副本,分别放在db0, db1。
.8. 在数据节点db0, db1创建维度表。
例如:

on db0:
create table test ( id int primary key, info varchar2(32), crt_time date);
on db1:
create table test ( id int primary key, info varchar2(32), crt_time date);

.9. 在PostgreSQL节点,创建分片表的外部表,必须包含CHECN约束。必须制定KEY,否则不能写。

create FOREIGN table tbl0 (id int OPTIONS (key 'true') , info varchar(32), crt_time timestamp without time zone) server db0 options (table 'tbl', schema 'username');
create FOREIGN table tbl1 (id int OPTIONS (key 'true') , info varchar(32), crt_time timestamp without time zone) server db1 options (table 'tbl', schema 'username');
create FOREIGN table tbl2 (id int OPTIONS (key 'true') , info varchar(32), crt_time timestamp without time zone) server db2 options (table 'tbl', schema 'username');
create FOREIGN table tbl3 (id int OPTIONS (key 'true') , info varchar(32), crt_time timestamp without time zone) server db3 options (table 'tbl', schema 'username');
alter foreign table tbl0 add constraint ck_tbl0 check (abs(mod(id,4))=0);
alter foreign table tbl1 add constraint ck_tbl1 check (abs(mod(id,4))=1);
alter foreign table tbl2 add constraint ck_tbl2 check (abs(mod(id,4))=2);
alter foreign table tbl3 add constraint ck_tbl3 check (abs(mod(id,4))=3);

.10. 在PostgreSQL节点,创建维度表的外部表

 create FOREIGN table test0 (id int OPTIONS (key 'true'), info varchar(32), crt_time timestamp without time zone) server db0 options (table 'test', schema 'username');
 create FOREIGN table test1 (id int OPTIONS (key 'true'), info varchar(32), crt_time timestamp without time zone) server db1 options (table 'test', schema 'username');

.11. 在PostgreSQL节点,创建分片表的父表,设置继承关系,触发器函数,触发器。

create table tbl (id int primary key, info varchar(32), crt_time timestamp without time zone);
alter foreign table tbl0 inherit tbl;
alter foreign table tbl1 inherit tbl;
alter foreign table tbl2 inherit tbl;
alter foreign table tbl3 inherit tbl;
create or replace function f_tbl_ins() returns trigger as $$
declare
begin
  case abs(mod(NEW.id, 4))
    when 0 then
      insert into tbl0 (id, info, crt_time) values (NEW.*);
    when 1 then
      insert into tbl1 (id, info, crt_time) values (NEW.*);
    when 2 then
      insert into tbl2 (id, info, crt_time) values (NEW.*);
    when 3 then
      insert into tbl3 (id, info, crt_time) values (NEW.*);
    else
      return null;
  end case;
    return null;
end;
$$ language plpgsql;
create trigger tg1 before insert on tbl for each row execute procedure f_tbl_ins();

.12. 在PostgreSQL节点,创建维度表的父表,设置继承关系,触发器函数,触发器。

create table test (id int primary key, info varchar(32), crt_time timestamp without time zone);
alter foreign table test0 inherit test;
-- 在不同的master节点,设置不同的继承,从而实现均衡查询的目的,目前PG内核还不支持维度表的负载均衡。
create or replace function f_test_iud() returns trigger as $$
declare
begin
  case TG_OP
    when 'INSERT' then
      insert into test0 (id, info, crt_time) values (NEW.*);
      insert into test1 (id, info, crt_time) values (NEW.*);
    when 'UPDATE' then
      update test0 set id=NEW.id,info=NEW.info,crt_time=NEW.crt_time where id=OLD.id and info=OLD.info and crt_time=OLD.crt_time;
      update test1 set id=NEW.id,info=NEW.info,crt_time=NEW.crt_time where id=OLD.id and info=OLD.info and crt_time=OLD.crt_time;
    when 'DELETE' then
      delete from test0 where id=OLD.id and info=OLD.info and crt_time=OLD.crt_time;
      delete from test1 where id=OLD.id and info=OLD.info and crt_time=OLD.crt_time;
  end case;
    return null;
end;
$$ language plpgsql;
create trigger tg1 before insert or update or delete on test for each row execute procedure f_test_iud();

现在,你可以测试这些表的插入,查询,更新,删除,JOIN。以及分布式事务。
插入tbl这个分片表时,会根据ID计算一个模值,插入到对应的分片节点。
更新,删除,查询时,如果提供了ID的模值,则会选择对应的子节点查询。
对于维度表test,查询时会自动查询test0, 更新,删除,插入则会在test0,test1同时操作 (非并行)。

使用这种方法给其他数据库做sharding, 除了EDB对Oracle兼容性比较好,其他的兼容性都需要用户去验证。
但是不管怎么样,用户可以获得如下好处:
ACID
分布式事务
跨库JOIN
主节点和数据节点都支持水平扩展
prepared statement
支持存储过程和函数

时间: 2024-10-29 17:38:49

PostgreSQL sharding for Oracle, SQL Server, DB2, Sybase的相关文章

asp.net 与 Oracle,SQL Server,Access 数据库类(1/8)

文章提供这款数据库教程连接代码是一款asp教程.net 与 oracle,sql server,access 数据库类哦, 如果你是asp.net教程开发者那你就爽了啊,这是一款利用了.net可以与oracle,sql server,access 进行连接哦,如果你用其这一种数据库就可以直接使用了,同时也解决了关于各种数据库连接问题. using system; using system.collections; using system.collections.specialized; usi

sql判断null Oracle,sql server

  sql server 替换null:isnull(arg,value) 如:select isnull(price,0.0) from orders ,如果price为null的话,用0.0替换 与null比较: is not null,is null 如 select * from orders where price is null ,price等于null 如: select * from orders where price is not null ,price不等于null ora

PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法_php技巧

Author: Wenlong Wu 一.针对MS SQL SERVER数据库 有两种解决方案,如下: 修改php.ini来实现: 打开php.ini,可看到mssql.textsize,mssql.textlimit两个选项: ; Valid range 0 - 2147483647. Default = 4096. ;mssql.textlimit = 4096 ; Valid range 0 - 2147483647. Default = 4096. ;mssql.textsize = 4

用SQL Server访问Sybase中的表的方法_数据库其它

问:SQL Server应该怎样访问Sybase数据库的表?  答:具体方法如下:  1: 安装Sybase客户端  版本的要求:  Sybase Client 11.9.2 for NT  1.1:安装完成后,运行开始->程序->Sybase->Dsedit  1.2:选择菜单的'Server Object',-> 'Add' 输入服务名 比如 1.70  1.3:然后在Server列表中选择'1.70',双击右边的对话框server address栏,在Network Addr

asp.net下Oracle,SQL Server,Access万能数据库通用类

复制代码 代码如下: using System; using System.Collections; using System.Collections.Specialized; using System.Data; using System.Data.SqlClient; using System.Data.OleDb; using System.Data.OracleClient; using System.Configuration; using System.Reflection; nam

Oracle SQL Server MySQL查看当前所有数据库表名及其他信息

环境:Oracle 11g + SQLServer 2008 R2 + MySQL 5.1 Oracle: 1. 查看当前库的所有数 据表 select * from all_tables; select table_name from all_tables; select table_name from user_tables; select table_name from all_tables where owner='用户名'; 2. 查看表结构 desc 表名 : SQLServer:

同时访问SQL SERVER和SYBASE数据库

对于一个系统管理员,要同时管理一个网络中的多个数据库服务器或者是互连网中分属不同网络的多个数据库服务器,首先要解决同时连通访问这些数据库服务器的问题.一般来说,各种数据库必须使用自己相应的客户端工具进行连接,而不能连接另外的数据库.微软公司的SQLSERVER6.0数据库是从SYBASE4.2数据库发展而来,其自身的客户端工具是不能连接SYBASE10或SYBASE11数据库的.另外SYBASE11客户端所带工具WISQLl32可以分段执行一个SQL文件中的任一选择部分,这样给管理数据库服务器,

使用IBM Data Movement Tool从SQL Server/Oracle到DB2的表数据迁移

SQL Server,Oracle 及 DB2 都是目前市场上很多应用程序所使用的关系型数据库,随着应用程序功能的日趋强大,应用程序的版本升级和重新安装都将要求保留原有数据.这样不同类型数据库之间的迁移成了现在应用程序功能中数据迁移部分的重点.目前市场上出现了一些数据库迁移工具(比如:IBM Data Movement Tool).互联网上针对这些工具的介绍大部分都是基于数据对象的整体迁移,也就是在数据结构迁移的基础上进行数据迁移.但是有些应用程序并不需要数据结构的迁移,而是仅仅需要表数据的迁移

SQL Server的链接服务器(MySQL、Oracle、Ms_sql、Access、SYBASE)

原文:SQL Server的链接服务器(MySQL.Oracle.Ms_sql.Access.SYBASE) 一.使用 Microsoft OLE DB Provider For ODBC 链接MySQL 安装MySQL的ODBC驱动MyODBC 1.为MySQL建立一个ODBC系统数据源,例如:选择数据库为test ,数据源名称为myDSN 2.建立链接数据库 EXEC sp_addlinkedserver @server = 'MySQLTest', @srvproduct='MySQL',