節(jié)點61/62(datanode)
CREATE TABLE users (username text, email text); insert into users values ('user0', 'user0@gmail.com'); insert into users values ('user1', 'user1@gmail.com'); insert into users values ('user2', 'user2@gmail.com');
節(jié)點60(proxy)
create or replace extension plproxy; CREATE FUNCTION get_user_email(i_username text) RETURNS SETOF text AS $$ CONNECT 'host=localhost port=9461 dbname=postgres connect_timeout=10'; SELECT email FROM users WHERE username = $1; $$ LANGUAGE plproxy; SELECT * from get_user_email('user0');
節(jié)點60(proxy)
CREATE FOREIGN DATA WRAPPER plproxy; CREATE SERVER usercluster FOREIGN DATA WRAPPER plproxy OPTIONS (connection_lifetime '1800', p0 'host=localhost port=9461 dbname=postgres connect_timeout=10', p1 'host=localhost port=9462 dbname=postgres connect_timeout=10' ); CREATE USER MAPPING FOR PUBLIC SERVER usercluster;
節(jié)點60(proxy)
CREATE OR REPLACE FUNCTION insert_user(i_username text, i_emailaddress text) RETURNS integer AS $$ CLUSTER 'usercluster'; RUN ON hashtext(i_username); $$ LANGUAGE plproxy;
節(jié)點61/62(datanode)
CREATE OR REPLACE FUNCTION insert_user(i_username text, i_emailaddress text) RETURNS integer AS $$ INSERT INTO users (username, email) VALUES ($1,$2); SELECT 1; $$ LANGUAGE SQL;
節(jié)點60(proxy)
SELECT insert_user('Sven','sven@somewhere.com'); SELECT insert_user('Marko', 'marko@somewhere.com'); SELECT insert_user('Steve','steve@somewhere.cm');
-- handler function CREATE FUNCTION plproxy_call_handler () RETURNS language_handler AS 'plproxy' LANGUAGE C; -- validator function CREATE FUNCTION plproxy_validator (oid) RETURNS void AS 'plproxy' LANGUAGE C; -- language CREATE LANGUAGE plproxy HANDLER plproxy_call_handler VALIDATOR plproxy_validator; -- validator function CREATE FUNCTION plproxy_fdw_validator (text[], oid) RETURNS boolean AS 'plproxy' LANGUAGE C; -- foreign data wrapper CREATE FOREIGN DATA WRAPPER plproxy VALIDATOR plproxy_fdw_validator;
補充:PostgreSQL 水平分庫——plproxy
1、1 編譯安裝
tar -zxvf plproxy-2.7.tar.gz cd plproxy-2.7 source /home/postgres/.bashrc make make install
1、2 創(chuàng)建pl/proxy擴展
itm_pg@pgs-> psql psql (10.3) Type "help" for help. postgres=# create database proxy; CREATE DATABASE postgres=# \c proxy You are now connected to database "proxy" as user "postgres". proxy=# create extension plproxy; CREATE EXTENSION proxy=# \dx List of installed extensions Name | Version | Schema | Description ---------+---------+------------+----------------------------------------------- ----------- plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language plproxy | 2.8.0 | public | Database partitioning implemented as procedura l language (2 rows)
修改數據庫節(jié)點pg_hba.conf:
修改兩個數據節(jié)點的pg_hba.conf,保證代理節(jié)點可以訪問。
# TYPE DATABASE USER ADDRESS METHOD host all all 192.168.7.177/32 trust
在SQL/MED方法在pl/proxy節(jié)點進行集群配置:
proxy=# create schema plproxy; --下面的函數都是創(chuàng)建在plproxy這個schema下面 CREATE SCHEMA proxy=# create user bill superuser; CREATE ROLE --創(chuàng)建一個使用plproxy FDW的服務器 proxy=# CREATE SERVER cluster_srv1 FOREIGN DATA WRAPPER plproxy proxy-# OPTIONS ( proxy(# connection_lifetime '1800', proxy(# disable_binary '1', proxy(# p0 'dbname=pl_db0 host=192.168.7.166', proxy(# p1 'dbname=pl_db1 host=192.168.17.190' proxy(# ); CREATE SERVER proxy=# \des List of foreign servers Name | Owner | Foreign-data wrapper --------------+-------+---------------------- cluster_srv1 | bill | plproxy (1 row) proxy=# grant usage on FOREIGN server cluster_srv1 to bill; GRANT --創(chuàng)建用戶映射 proxy=# create user mapping for bill server cluster_srv1 options (user 'bill'); CREATE USER MAPPING proxy=# \deu List of user mappings Server | User name --------------+----------- cluster_srv1 | bill (1 row)
配置完成!在"CLUSTER"模式中;才需要上述配置;在"CONNECT"模式中是不需要的。
在兩個數據節(jié)點創(chuàng)建測試表:
postgres=# create database pl_db1; CREATE DATABASE postgres=# create user bill superuser; CREATE ROLE postgres=# \c pl_db1 bill You are now connected to database "pl_db1" as user "bill". pl_db1=# create table users(userid int, name text); CREATE TABLE
3、1數據水平拆分測試
在每個數據節(jié)點創(chuàng)建insert函數接口
pl_db1=# CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) pl_db1-# RETURNS integer AS $$ pl_db1$# INSERT INTO users (userid, name) VALUES ($1,$2); pl_db1$# SELECT 1; pl_db1$# $$ LANGUAGE SQL; CREATE FUNCTION
–pl_db0節(jié)點一樣
2、在PL/Proxy數據庫創(chuàng)建同名的insert函數接口
proxy=# CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) proxy-# RETURNS integer AS $$ proxy$# CLUSTER 'cluster_srv1'; proxy$# RUN ON ANY; proxy$# $$ LANGUAGE plproxy; CREATE FUNCTION
3、在PL/Proxy數據庫創(chuàng)建讀的函數get_user_name()
proxy=# CREATE OR REPLACE FUNCTION get_user_name() proxy-# RETURNS TABLE(userid int, name text) AS $$ proxy$# CLUSTER 'cluster_srv1'; proxy$# RUN ON ALL ; proxy$# SELECT userid,name FROM users; proxy$# $$ LANGUAGE plproxy; CREATE FUNCTION
4、在pl/proxy節(jié)點插入數據進行測試
SELECT insert_user(1001, 'Sven'); SELECT insert_user(1002, 'Marko'); SELECT insert_user(1003, 'Steve'); SELECT insert_user(1004, 'bill'); SELECT insert_user(1005, 'rax'); SELECT insert_user(1006, 'ak'); SELECT insert_user(1007, 'jack'); SELECT insert_user(1008, 'molica'); SELECT insert_user(1009, 'pg'); SELECT insert_user(1010, 'oracle');
5、在節(jié)點數據庫查看數據分布情況
pl_db1=# select * from users; userid | name --------+------- 1001 | Sven 1003 | Steve 1004 | bill (3 rows)
我們在proxy節(jié)點查詢下:
proxy=# SELECT USERID,NAME FROM GET_USER_NAME(); userid | name --------+-------- 1005 | rax 1006 | ak 1008 | molica 1009 | pg 1002 | Marko 1004 | bill 1007 | jack 1010 | oracle 1001 | Sven 1003 | Steve (10 rows)
因為創(chuàng)建insert_user函數時使用的是ROW ON ANY,表示隨機再一臺機器上進行執(zhí)行,因此實現了數據在不同節(jié)點的隨機分布,接下來改成ROW ON ALL,實驗在不同節(jié)點進行數據的復制。
run on , 是數字常量, 范圍是0 到 nodes-1; 例如有4個節(jié)點 run on 0; (run on 4則報錯).
run on ANY,
run on function(…), 這里用到的函數返回結果必須是int2, int4 或 int8.
run on ALL, 這種的plproxy函數必須是returns setof…, 實體函數沒有setof的要求.
3、2數據復制測試
選擇users表作為實驗對象;我們先清理表users數據;在數據節(jié)點創(chuàng)建truncatet函數接口
pl_db1=# CREATE OR REPLACE FUNCTION trunc_user() pl_db1-# RETURNS integer AS $$ pl_db1$# truncate table users; pl_db1$# SELECT 1; pl_db1$# $$ LANGUAGE SQL; CREATE FUNCTION
2、在PL/Proxy數據庫創(chuàng)建同名的truncate函數接口
proxy=# CREATE OR REPLACE FUNCTION trunc_user() proxy-# RETURNS SETOF integer AS $$ proxy$# CLUSTER 'cluster_srv1'; proxy$# RUN ON ALL; proxy$# $$ LANGUAGE plproxy; CREATE FUNCTION
–檢查發(fā)現數據已經清理掉了
proxy=# SELECT TRUNC_USER(); trunc_user ------------ 1 1 (2 rows)
3、在PL/Proxy數據庫創(chuàng)建函數接口 insert_user_2
proxy=# CREATE OR REPLACE FUNCTION insert_user_2(i_id int, i_name text) proxy-# RETURNS SETOF integer AS $$ proxy$# CLUSTER 'cluster_srv1'; proxy$# RUN ON ALL; proxy$# TARGET insert_user; proxy$# $$ LANGUAGE plproxy; CREATE FUNCTION
4、插入幾條數據
proxy=# SELECT insert_user_2(1004, 'bill'); insert_user_2 --------------- 1 1 (2 rows) proxy=# SELECT insert_user_2(1005, 'rax'); insert_user_2 --------------- 1 1 (2 rows) proxy=# SELECT insert_user_2(1006, 'ak'); insert_user_2 --------------- 1 1 (2 rows) proxy=# SELECT insert_user_2(1007, 'jack'); insert_user_2 --------------- 1 1 (2 rows)
5、查看每個節(jié)點數據情況
pl_db1=# select * from users; userid | name --------+------- 1004 | bill 1005 | rax 1006 | ak 1007 | jack (4 rows) pl_db0=# select * from users; userid | name --------+------- 1004 | bill 1005 | rax 1006 | ak 1007 | jack (4 rows)
兩個數據節(jié)點的數據一樣,實現了數據的復制。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。