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

为何current_setting()值在PostgreSQL异常块中显示未定义?

PostgreSQL中set_config设置的参数在异常块中读取不到的原因

问题描述

使用set_config()设置配置参数后,正常执行块中可通过current_setting()读取该参数,但触发异常进入异常块后,参数显示未定义。

代码示例

do $$declare
    l_ctx_prm text := 'some_value'; 
    l_dummy numeric;
begin
    raise notice 'test before set_config: [utl_log.test_ctx=%]', current_setting('utl_log.test_ctx', true);  
    perform set_config('utl_log.test_ctx', l_ctx_prm, false);
    raise notice 'test after set_config: [utl_log.test_ctx=%]', current_setting('utl_log.test_ctx', true);  
    l_dummy := 1/0; -- 触发异常
exception when others then
    raise notice 'test in exception block: [utl_log.test_ctx=%]', current_setting('utl_log.test_ctx', true);  
end$$;

执行结果

test before set_config: [utl_log.test_ctx=<NULL>]
test after set_config: [utl_log.test_ctx=some_value]
test in exception block: [utl_log.test_ctx=]

原因解释

这是PostgreSQL事务机制的特性导致的:

  • 整个DO块会作为一个独立事务执行;
  • 当事务内触发异常时,所有事务内的变更都会被回滚,包括通过set_config('utl_log.test_ctx', l_ctx_prm, false)对会话级参数的修改;
  • 异常块的执行是在事务回滚完成之后,此时该参数已恢复到修改前的未定义状态,因此current_setting返回空值。

解决方案

如果需要在异常块中获取该参数值,推荐直接将参数存储到PL/pgSQL变量中,异常块可直接读取变量值,无需依赖会话参数:

do $$declare
    l_ctx_prm text := 'some_value'; 
    l_dummy numeric;
begin
    raise notice 'test before set_config: [utl_log.test_ctx=%]', current_setting('utl_log.test_ctx', true);  
    perform set_config('utl_log.test_ctx', l_ctx_prm, false);
    raise notice 'test after set_config: [utl_log.test_ctx=%]', current_setting('utl_log.test_ctx', true);  
    l_dummy := 1/0; -- 触发异常
exception when others then
    -- 直接读取变量而非会话参数
    raise notice 'test in exception block: [l_ctx_prm=%]', l_ctx_prm;  
end$$;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:37:32