postgresql - postgresql:测试 dblink 连接的触发器,如果不存在则建立
问题描述
我正在尝试在 postgresql 9.6 中设置一个触发器,当将一行插入到它自己的表中时,它将使用 dblink 将一行插入到另一个数据库中。由于这些插入量可能很大,我不想在每次插入时都连接和断开与数据库的连接,所以我希望有一个持久连接,每次插入都使用它。但我想我必须测试连接是否可用,因为很多事情都可能导致连接断开。
我的伪代码如下:
-- 1. test if named dblink connection already exists
-- 2. if it does not, create a named dblink connection
-- 3. insert data via dblink
我到目前为止是这样的:
CREATE OR REPLACE FUNCTION db_link_trigger()
RETURNS trigger AS
$BODY$
BEGIN
-- 1. test if named dblink connection already exists
IF (SELECT COALESCE('dblinktest' = ANY (dblink_get_connections()), false)) = false THEN
-- 2. if it does not, create a named dblink connection
RAISE NOTICE 'dblink connection not established. Connecting now';
PERFORM dblink_connect('dblinktest', 'hostaddr=192.168.1.30 port=5433 dbname=otherdb user=myuser password=mypassword');
ELSE
RAISE NOTICE 'dblink connection already established';
END IF;
-- 3. insert data via dblink
PERFORM dblink_exec('dblinktest', 'insert into mytable(data) values(''' || NEW.data || ''');');
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
我主要关心的是如何处理错误以及如何处理触发器的近乎同时调用。考虑两个 INSERTS 是否同时进入,并且之前没有名为 'dblinktest' 的 dblink。当第一个发现连接不存在时,它会继续设置它。然后第二个可以看到链接也没有建立并尝试连接自己,但它会失败,因为第一个会在它之前连接,它会引发错误:
ERROR: duplicate connection name
我该如何处理这样的错误?postgresql 有类似这种受 python 启发的伪代码吗?
try:
if dblink connection is not established:
establish dblink connection
except 'ERROR: duplicate connection name':
pass # do nothing
finally:
insert row into other db via dblink connection
解决方案
您可以从此链接https://www.postgresql.org/docs/10/errcodes-appendix.html获取错误代码,这种情况是:
42710 -> 重复对象
并使用带有 EXCEPTION 子句的 PL/pgSQL BEGIN 块管理此错误
例如:
CREATE OR REPLACE FUNCTION db_link_function()
RETURNS void AS
$BODY$
declare
rec record;
BEGIN
BEGIN
PERFORM dblink_connect('dblinktest', 'hostaddr=127.0.0.1 port=5435 dbname=dell user=postgres password=password');
--the EXCEPTION
EXCEPTION
WHEN duplicate_object THEN --code error 42710
RAISE NOTICE 'this connections exists';
END;
--select data via dblink
SELECT * FROM dblink('dblinktest','SELECT * FROM categories where category=1') AS t(cid int, cname text) into rec;
raise notice 'value of rec: %,%', rec.cid, rec.cname;
END;
$BODY$
LANGUAGE plpgsql;
我建议使用 FDW 而不是 dblink https://www.postgresql.org/docs/10/postgres-fdw.html
推荐阅读
- c# - 使用 NAudio 读取包含作品音频的 MemoryStream
- python - Python 无法打开程序:加载组件时出错
- python - 如何一次有效地运行多个 Pytorch 进程/模型?Traceback:分页文件太小,无法完成此操作
- python - 无法在 django 项目中创建过滤器
- reactjs - 如何使用 SpeedDial 上传文件?
- python - Numpy - 有没有办法指定广播维度?
- python - 如何将 3D 数组的 python 列表转换为特定形状的单个 3D 数组?
- c - 如何将二维用户输入的数组从函数传递到 main()?
- serverless-framework - 具有 API 网关、Lambda 层和 Webpack 的无服务器框架(配置地狱)
- javascript - JavaScript - 在 ECharts 中显示带有字典的条形图