本期问答如下:
- 如何获取业务函数设置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%';
系统表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。
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等方式进行处理。