PL/Proxy插件包含CLUSTER模式和CONNECT模式,可以幫助您用不同方式訪問數據庫。
您可以加入RDS PostgreSQL插件交流釘釘群(103525002795),進行咨詢、交流和反饋,獲取更多關于插件的信息。
前提條件
背景信息
PL/Proxy插件包含如下兩種模式:
CLUSTER模式
支持數據庫水平拆分和SQL復制。
CONNECT模式
支持將SQL請求路由到指定的數據庫。
更多PL/Proxy插件使用方法請參見PL/Proxy。
注意事項
相同VPC內的PostgreSQL實例可以直接跨庫操作。
不同VPC內的PostgreSQL實例可以通過本VPC內的ECS實例進行端口跳轉,實現跨庫操作。
代理節點后端的數據節點數必須是2的N次方。
測試環境
選擇一個數據庫實例作為代理節點,另外兩個數據庫實例作為數據節點。詳細信息如下。
IP | 節點類型 | 數據庫名 | 用戶名 |
100.xx.xx.136 | 代理節點 | postgres | postgres |
100.xx.xx.72 | 數據節點 | pl_db0 | postgres |
11.xx.xx.9 | 數據節點 | pl_db1 | postgres |
創建PL/Proxy插件
創建PL/Proxy插件命令如下:
create extension plproxy
創建PL/Proxy集群
CONNECT模式不需要進行本操作。
創建PL/Proxy集群,指定連接的子節點的數據庫名、IP地址和端口,示例如下:
postgres=# CREATE SERVER cluster_srv1 FOREIGN DATA WRAPPER plproxy postgres-# OPTIONS ( postgres(# connection_lifetime '1800', postgres(# disable_binary '1', postgres(# p0 'dbname=pl_db0 host=100.xxx.xxx.72 port=5678', postgres(# p1 'dbname=pl_db1 host=11.xxx.xxx.9 port=5678' postgres(# ); CREATE SERVER
為postgres用戶賦予權限,示例如下:
postgres=# grant usage on FOREIGN server cluster_srv1 to postgres; GRANT
創建用戶映射,示例如下:
postgres=> create user mapping for postgres server cluster_srv1 options (user 'postgres'); CREATE USER MAPPING
創建測試表
在每個數據節點創建測試表(代理節點不需要創建),示例如下:
create table users(userid int, name text);
CLUSTER模式測試
數據水平拆分測試步驟如下:
在每個數據節點創建插入函數,示例如下:
pl_db0=> CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) pl_db0-> RETURNS integer AS $$ pl_db0$> INSERT INTO users (userid, name) VALUES ($1,$2); pl_db0$> SELECT 1; pl_db0$> $$ LANGUAGE SQL; CREATE FUNCTION 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
在代理節點創建同名的插入函數,示例如下:
postgres=> CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) postgres-> RETURNS integer AS $$ postgres$> CLUSTER 'cluster_srv1'; postgres$> RUN ON ANY; postgres$> $$ LANGUAGE plproxy; CREATE FUNCTION
在代理節點創建讀取函數,示例如下:
postgres=> CREATE OR REPLACE FUNCTION get_user_name() postgres-> RETURNS TABLE(userid int, name text) AS $$ postgres$> CLUSTER 'cluster_srv1'; postgres$> RUN ON ALL ; postgres$> SELECT userid,name FROM users; postgres$> $$ LANGUAGE plproxy; CREATE FUNCTION
在代理節點插入10條測試記錄,示例如下:
SELECT insert_user(1001, 'Sven'); SELECT insert_user(1002, 'Marko'); SELECT insert_user(1003, 'Steve'); SELECT insert_user(1004, 'lottu'); 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');
由于插入函數執行的是RUN ON ANY,即插入數據時隨機選取數據節點,查看每個數據節點的數據如下:
pl_db0=> select * from users; userid | name --------+-------- 1001 | Sven 1003 | Steve 1004 | lottu 1005 | rax 1006 | ak 1007 | jack 1008 | molica 1009 | pg (8 rows) pl_db1=> select * from users; userid | name --------+-------- 1002 | Marko 1010 | oracle (2 rows)
說明通過查詢可以發現10條數據分布在不同數據節點,由于10條數據太少,導致分布不均勻。
在代理節點執行讀取函數,由于執行的是RUN ON ALL,即代理節點返回所有數據節點查詢結果,示例如下:
postgres=> SELECT USERID,NAME FROM GET_USER_NAME(); userid | name --------+-------- 1001 | Sven 1003 | Steve 1004 | lottu 1005 | rax 1006 | ak 1007 | jack 1008 | molica 1009 | pg 1002 | Marko 1010 | oracle (10 rows)
SQL復制測試步驟如下:
在各個節點創建清理函數用于清理表users數據,示例如下:
pl_db0=> CREATE OR REPLACE FUNCTION trunc_user() pl_db0-> RETURNS integer AS $$ pl_db0$> truncate table users; pl_db0$> SELECT 1; pl_db0$> $$ LANGUAGE SQL; CREATE FUNCTION 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 postgres=> CREATE OR REPLACE FUNCTION trunc_user() postgres-> RETURNS SETOF integer AS $$ postgres$> CLUSTER 'cluster_srv1'; postgres$> RUN ON ALL; postgres$> $$ LANGUAGE plproxy; CREATE FUNCTION
在代理節點執行清理函數,示例如下:
postgres=> SELECT TRUNC_USER(); trunc_user ------------ 1 1 (2 rows)
在代理節點創建插入函數,示例如下:
postgres=> CREATE OR REPLACE FUNCTION insert_user_2(i_id int, i_name text) postgres-> RETURNS SETOF integer AS $$ postgres$> CLUSTER 'cluster_srv1'; postgres$> RUN ON ALL; postgres$> TARGET insert_user; postgres$> $$ LANGUAGE plproxy; CREATE FUNCTION
在代理節點插入4條測試記錄,示例如下:
SELECT insert_user_2(1004, 'lottu'); SELECT insert_user_2(1005, 'rax'); SELECT insert_user_2(1006, 'ak'); SELECT insert_user_2(1007, 'jack');
查看每個數據節點的數據,示例如下:
pl_db0=> select * from users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 rows) pl_db1=> select * from users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 rows)
說明每個數據節點的數據都一樣,說明數據復制成功。
在代理節點查詢時,只需要執行RUN ON ANY,即在任意一個數據節點讀取數據即可,示例如下:
postgres=> CREATE OR REPLACE FUNCTION get_user_name_2() postgres-> RETURNS TABLE(userid int, name text) AS $$ postgres$> CLUSTER 'cluster_srv1'; postgres$> RUN ON ANY ; postgres$> SELECT userid,name FROM users; postgres$> $$ LANGUAGE plproxy; CREATE FUNCTION postgres=> SELECT USERID,NAME FROM GET_USER_NAME_2(); userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 rows)
CONNECT模式測試
使用CONNECT模式時,代理節點可以直接跨實例訪問,示例如下:
postgres=> CREATE OR REPLACE FUNCTION get_user_name_3()
postgres-> RETURNS TABLE(userid int, name text) AS $$
postgres$> CONNECT 'dbname=pl_db0 host=100.81.137.72 port=56789';
postgres$> SELECT userid,name FROM users;
postgres$> $$ LANGUAGE plproxy;
CREATE FUNCTION
postgres=> SELECT USERID,NAME FROM GET_USER_NAME_3();
userid | name
--------+-------
1004 | lottu
1005 | rax
1006 | ak
1007 | jack
(4 rows)