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

PostgreSQL问答-第26期

原创 多米爸比 2023-06-17
1740

本期问答如下:

  • 备份session超时问题
  • rm清理归档无影响
  • 阶乘操作符已废弃
  • 参数化语句分析

Q1.基础备份session超时

问题描述

使用pg_basebackup或pg_probackup第三方备份工具进行备份时提示空闲会话超时,错误信息如下:

FATAL: terminating connection due to idle-session timeout

问题解答

执行基础备份时,会调用pg_start_backup、pg_stop_backup、replication命令或progress进度函数进行query查询,在PostgreSQL 14或以上版本如果数据库设置了session超时参数(版本14引入的新参数)idle_session_timeout,那基础备份发起的query查询会超时失败。

如果用户环境因为安全性要求设置了空闲会话超时,可以单独对备份用户设置该参数,参考命令如下:

alter user backup set session_timeout to 0;

然后使用backup用户进行备份。

Q2.清理归档WAL文件使用rm进行删除对数据库有什么影响。

在PostgreSQL数据库里可以使用pg_archivecleanup工具进行归档清理,也可以自己写脚本进行删除。

对于使用脚本直接rm删除归档的方式,Oracle同事会存在疑虑:
不通过数据库工具pg_archivecleanup进行操作,数据库是否能感知,数据库是否会认为并没有删除呢?

通过archive_command归档的WAL文件存储在于外部路径,也没有与PGDATA有任何关联,不会与PostgreSQL数据库有直接影响,归档清理通常可以在做完PITR时间点恢复后再调用pg_archivecleanup工具去清理不需要的WAL文件。

另外归档配置除了archive_command,从PostgreSQL 15开始也可以尝试basic_archive模块提供的archive_library参数进行更加高效的归档管理。

Q3.阶乘操作符"!"不支持

问题描述

在PostgreSQL 14之前可以阶乘操作符"!",如下所示:

psql (13.10) Type "help" for help. postgres=# select 3!; ┌──────────┐ │ ?column? │ ├──────────┤ │ 6 │ └──────────┘ (1 row)

在PostgreSQL 14或以上版本执行则会提示错误:

psql (15.3) Type "help" for help. postgres=# select 3!; ERROR: syntax error at or near ";" LINE 1: select 3!; ^

问题解答

查看特性提交邮件,PostgreSQL 14之前阶乘有三种方式可以使用:操作符"!"、factorial函数、numeric_fac函数。

"!"操作符是内置postfix风格的操作符,通常我们应该使用factorial函数,numeric_fac函数是一个SQL别名函数。

从PostgreSQL 14版本开始只保留factorial函数,因此最通用的使用方式是使用factorial函数。

postgres=# select factorial(3); ┌───────────┐ │ factorial │ ├───────────┤ │ 6 │ └───────────┘ (1 row)

Q4.参数化语句如何分析性能

问题描述

当我们分析查询语句的性能时,如果不知道参数的值,很难使用EXPLAIN分析执行计划。

postgres=# explain SELECT oid FROM pg_class WHERE relname = $1; ERROR: there is no parameter $1 LINE 1: explain SELECT oid FROM pg_class WHERE relname = $1; ^

问题解答

使用扩展查询语句可以分离SELECT, INSERT, UPDATE, DELETE语句(不包括ALTER)和语句中使用的常量,参数化语句可以增强安全性,它可以防止SQL注入,同时也可以提升性能。因为PostgreSQL根据plan_cache_mode的默认值可以在单个会话里基于6次启发式缓存参数化语句的通用执行计划。

不过在偏OLAP场景下,运行耗时的分析查询,获得最佳的执行计划更加重要,此时我们可以把plan_cache_mode的默认值auto调整为force_custom_plan。

在日常的数据库日志或pg_stat_statements中发现问题语句,为了便于EXPLAIN获得执行计划分析参数化语句的性能,可以设置plan_cache_mode的值为force_generic_plan,借助通用执行计划来忽略参数的值。

针对上面的语句,我们先使用PREPARE创建参数化语句:

PREPARE stmt(unknown) AS SELECT oid FROM pg_class WHERE relname = $1;

这里假定不知道参数的数据类型,使用伪类型"unknown",稍后让数据库根据上下文解析合适的数据类型。

再设置plan_cache_mode为"force_generic_plan"

SET plan_cache_mode = force_generic_plan;

最后使用NULL作为参数执行

postgres=# EXPLAIN EXECUTE stmt(NULL); ┌───────────────────────────────────────────────────────────────────────────────────────────┐ │ QUERY PLAN │ ├───────────────────────────────────────────────────────────────────────────────────────────┤ │ Index Scan using pg_class_relname_nsp_index on pg_class (cost=0.28..8.29 rows=1 width=4) │ │ Index Cond: (relname = $1) │ └───────────────────────────────────────────────────────────────────────────────────────────┘ (2 rows)

而即将发布的PostgreSQL 16对EXPLAIN增加了一个generic_plan选项,可以更加简便的获取通用执行计划,如下:

postgres=# EXPLAIN(generic_plan) SELECT oid FROM pg_class WHERE relname = $1; ┌───────────────────────────────────────────────────────────────────────────────────────────┐ │ QUERY PLAN │ ├───────────────────────────────────────────────────────────────────────────────────────────┤ │ Index Scan using pg_class_relname_nsp_index on pg_class (cost=0.27..8.29 rows=1 width=4) │ │ Index Cond: (relname = $1) │ └───────────────────────────────────────────────────────────────────────────────────────────┘ (2 rows)

最后推荐使用pgbadger日志分析工具,借助–dump-all-queries选项可以把参数值自动替换到语句中,再进行分析。

参考如下:

image.png

https://kmoppel.github.io/2023-06-07-til-filling-prepared-statement-placeholders-automatically-with-pgbadger/

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

文章被以下合辑收录

评论