暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

PostgreSQL问题分享-第29期

原创 多米爸比 2023-08-24
443

本期问答如下:

  • 如何获取业务函数设置GUC参数的证据
  • pg_upgrade工具升级大版本时提示表空间目录已存在
  • systemd与RemoveIPC参数
  • prepareThreshold参数在JDBC的作用
  • 使用pg_dumpall拆分导出后导入提示对象不存在

Q1.如何获取业务函数设置GUC参数的证据

怀疑业务函数里设置了work_mem参数引起服务器内存波动,在数据库系统字典是否能查到相应的证据呢?

使用下面两个函数进行模拟:

create or replace function test1()
returns void
as $function$
declare
begin
    return ;
end;
$function$ language plpgsql set work_mem='8MB';

test1函数属性上直接设置,test2函数在函数体里设置

create or replace function test2()
returns void
as $function$
declare
begin
    set work_mem='8MB';
    return ;
end;
$function$ language plpgsql ;

查询pg_proc即可获取所需信息

select prosrc,proconfig from pg_proc where proname like 'test%';

image.png

系统表pg_proc的proconfig直接记录了配置参数,函数体里如果有参数设置可以通过prosrc模糊查询参数名。

Q2.pg_upgrade工具升级大版本时提示表空间目录已存在

使用pg_upgrade工具升级12到13,升级过程可能会失败,失败的原因可能是扩展插件缺失或一些版本兼容性的变化引起。

当我们使用了自定义表空间,如果升级过程失败,则在低版本的数据目录复制的新版本表空间目录还未完全拷贝到高版本数据目录下,此时残留的高版本表空间目录不会自动删除,再次尝试升级时会出现如下错误提示:

new cluster tablespace directory already exists: "/pg_tablespace/PG_13_202007201"
Failure, exiting

此时需要先手工清理每个表空间的如下目录,参考操作命令如下:

rm -rf */PG_13_202007201

Q3.systemd与RemoveIPC参数

某客户环境在Ubuntu20.04操作系统中使用PG 15.3源码安装的数据库,偶尔会出现报错:

[58P01] FATAL: could not open shared memory segment"/PostgreSQL.2371031690": No such file or directory;

该错误信息在官方文档上有记录,当使用systemd管理服务,并且PG是源码安装时推荐关闭RemoveIPC参数,设置RemoveIPC=no。

image.png

Q4.prepareThreshold参数在JDBC的作用

很多人了解PG数据库的plan_cache_mode参数,该参数的作用相当于Oracle数据库的绑定变量窥视功能。plan_cache_mode参数默认值为auto,默认前五次使用硬解析产生custom plan,第六次可能会使用软解析generic plan。

不过应用程序使用jdbc进行连接时,prepareThreshold参数可以开启是否使用服务端绑定变量。值为0时,相当于硬解析,值为1时,每次都复用SQL解析结果和执行计划,默认值为5,保持与服务端五次启发式缓存执行计划。

一些场景下可以设置prepareThreshold = 0,禁用plan cache。

Q5.使用pg_dumpall拆分导出后导入提示对象不存在

超级用户postgres使用pg_dumpall分三次分别导出全局对象、结构、数据如下:

pg_dumpall -v -g -f t1_global_exp.sql 
pg_dumpall -v -s -f t1_schema_exp.sql 
pg_dumpall -v -a -f t1_data_exp.sql 

然后使用psql导入

psql -f t1_global_exp.sql 
psql -f t1_schema_exp.sql 
psql -f t1_data_exp.sql

执行最后一条数据导入语句时会提示:

ERROR:  relation "t2" does not exist...
...
CONTEXT:  PL/pgSQL function ...

经过分析是普通用户有使用触发器,触发器函数里引用的表(例如下面的t2表)被其他用户触发时因未显式使用模式前缀而找不到表对象。

CREATE FUNCTION f1() RETURNS TRIGGER AS $BODY$
declare
  v1 varchar;
BEGIN
    select info into v1 from t2 where id = 200;
    NEW.info=v1;
RETURN NEW;
END
$BODY$ LANGUAGE PLPGSQL;

使用pg_dumpall拆分导出导入时需要检查insert触发器里对象的schema,或者导入前设置用户的search_path等方式进行处理。

最后修改时间:2023-11-11 11:48:15
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论