You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dblink查询超时后如何让PostgreSQL存储过程继续循环执行

解决dblink查询超时后继续循环的问题

核心问题

常规when others捕获逻辑无法妥善处理dblink超时对应的SQL state: 57014异常,且超时后dblink连接会进入无效状态,若不主动清理会阻断后续循环执行。

修改后的代码实现

for rec in (select dbc.db_name, dbc.con_string || ' options = ''-c statement_timeout='||_queryTimeout*1000||''' ' as con_string
            from db_connections dbc
            )
LOOP
    exceptionMsg := '';
    raise notice '% start',  rec.db_name ;

    BEGIN
        PERFORM dblink_connect(rec.db_name, rec.con_string); 

        insert into results_tbl (db_name, value, query_text)
            select rec.db_name, value, _queryText
            from dblink(rec.db_name, format($query$
                select json_agg(x.*)::text from (%1$s)x
                $query$, _queryText 
            ) ) r (value text);

        PERFORM dblink_disconnect(rec.db_name);
    EXCEPTION
        -- 专门捕获statement timeout异常(SQLSTATE 57014)
        WHEN SQLSTATE '57014' THEN
            GET STACKED DIAGNOSTICS exceptionMsg = message_text;
            RAISE NOTICE ' ******TIMEOUT EXCEPTION*******
            Database: %
            Message: %
            **************', rec.db_name, exceptionMsg;
            -- 强制断开无效连接
            PERFORM dblink_disconnect(rec.db_name);
        -- 捕获其他所有异常
        WHEN OTHERS THEN
            GET STACKED DIAGNOSTICS exceptionMsg = message_text;
            RAISE NOTICE ' ******GENERAL EXCEPTION*******
            Database: %
            Message: %
            **************', rec.db_name, exceptionMsg;
            -- 清理异常连接
            PERFORM dblink_disconnect(rec.db_name);
    END;

    COMMIT;
    raise notice '% done',  rec.db_name ;
END LOOP;

关键修改点

  • 精准捕获超时异常:单独指定SQLSTATE '57014'捕获超时场景,日志信息更清晰。
  • 强制清理无效连接:无论执行成功还是异常(含超时),都确保执行dblink_disconnect,避免无效连接占用资源或阻断后续操作。
  • 调整代码结构:将dblink_connect移入内部事务块,确保连接失败时也能进入异常处理逻辑,避免连接泄露。
  • 增强日志定位:在通知中加入数据库名称,快速定位异常来源库。

兼容旧版本补充

若使用的PostgreSQL版本较旧,dblink_disconnect在无效连接上执行可能抛出新异常,可嵌套小事务块处理:

BEGIN
    PERFORM dblink_disconnect(rec.db_name);
EXCEPTION WHEN OTHERS THEN
    RAISE NOTICE 'Failed to disconnect from %: %', rec.db_name, SQLERRM;
END;

内容的提问来源于stack exchange,提问作者sh4rkyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:20:27