PostgreSQL日志中的SQL记录时机 —— log_statement 和 log_min_duration_statement
最近跟朋友讨论到PostgreSQL日志中的SQL记录时机,研究了下log_statement 和 log_min_duration_statement两个参数,记录一下。
一、 参数简介
1. log_statement
① 作用
控制记录SQL的类型,可选值为:
- none:关闭(默认)
- ddl:DDL语句
- mod:DDL和所有涉及数据修改的语句(DML、COPY FROM、PREPARE、EXECUTE等)。对于explain和explain analyze,如果后面的语句类型符合,也会被记录
- all:所有语句
② 记录时机
SQL语句解析成功后,执行前。因此即使设置为all,也不会记录有语法错误的语句(如果想记录,应该使用log_min_error_statement参数)。
③ 记录内容
记录SQL语句,包含参数,但不包含执行用户、主机名等信息,这些需要审计插件才有。
2. log_min_duration_statement
① 作用
记录超过指定执行时间阈值的SQL,可选值为:
- -1:关闭(默认)
- 0:所有语句
- 正数:慢SQL阈值
② 记录时机
SQL语句执行完成后,因此能记录到执行时间。
③ 记录内容
- 记录SQL语句、执行时间,但不包含参数。
- 对于使用扩展查询协议的客户端,对语法分析、绑定、执行每一步所花时间会独立记录。
3. 同时符合两者的SQL会如何?
- 语句在解析完成后、执行开始前,即被记入日志(log_statement生效)
- 语句执行完成后,单独将duration记入日志(log_min_duration_statement生效),但不再重复记录语句
- 因此建议使用log_line_prefix记录PID或会话ID,避免duration和语句关联不上
二、 效果测试
1. 两者均设置
log_statement='all',log_min_duration_statement='0s'
2023-11-28 17:51:45.222 CST [2484] LOG: statement: select pg_sleep(10);
2023-11-28 17:51:55.227 CST [2484] LOG: duration: 10005.249 ms
语句记录为开始时间(log_statement生效),duration在执行完成时单独记录(log_min_duration_statement生效),但不再重复记录语句。
2. 仅设置log_statement
log_statement='all',log_min_duration_statement='-1'(禁用)
2023-11-28 17:53:49.540 CST [2760] LOG: statement: select pg_sleep(10);
仅记录语句,记录时间为开始时间,没有duration
3. 仅设置log_min_duration_statement
log_statement='none'(禁用),log_min_duration_statement='0s'
2023-11-28 17:55:20.288 CST [2826] LOG: duration: 15015.447 ms statement: select pg_sleep(15);
记录语句和duration,记录时间为结束时间
三、 参数记录时机
从上面文档可以知道,两个参数记录时机都在SQL执行阶段,只是一个在前一个在后。源码中SQL执行相关的函数主要是exec_simple_query,因此我们就看看这个函数。
函数刚开头就可以看到 pg_parse_query 和 check_log_statement函数。
/** exec_simple_query** Execute a "simple Query" protocol message.*/
static void
exec_simple_query(const char *query_string)
{CommandDest dest = whereToSendOutput;MemoryContext oldcontext;List *parsetree_list;ListCell *parsetree_item;bool save_log_statement_stats = log_statement_stats;bool was_logged = false;bool use_implicit_block;char msec_str[32];
.../** Do basic parsing of the query or queries (this should be safe even if* we are in aborted transaction state!)*/parsetree_list = pg_parse_query(query_string);/* Log immediately if dictated by log_statement */if (check_log_statement(parsetree_list)){ereport(LOG,(errmsg("statement: %s", query_string),errhidestmt(true),errdetail_execute(parsetree_list)));was_logged = true;}
- pg_parse_query函数用于SQL解析,符合log_statement记录的语句发生在解析完成后
- check_log_statement函数就用于检查log_statement的设置,标记是否需要记录
- was_logged=true表示已记录SQL语句,主要是给后面的慢SQL记录函数,提示其不需重复记录SQL文本
/** check_log_statement* Determine whether command should be logged because of log_statement** stmt_list can be either raw grammar output or a list of planned* statements*/
static bool
check_log_statement(List *stmt_list)
{ListCell *stmt_item;if (log_statement == LOGSTMT_NONE)return false;if (log_statement == LOGSTMT_ALL)return true;/* Else we have to inspect the statement(s) to see whether to log */foreach(stmt_item, stmt_list){Node *stmt = (Node *) lfirst(stmt_item);if (GetCommandLogLevel(stmt) <= log_statement)return true;}return false;
}
后面一大堆是SQL执行相关的代码,非本次重点,直接拉到函数末尾,可以看到check_log_duration函数,看名字都能猜到是它了,也符合在SQL执行完才记录。
.../** Emit duration logging if appropriate.*/switch (check_log_duration(msec_str, was_logged)){case 1:ereport(LOG,(errmsg("duration: %s ms", msec_str),errhidestmt(true)));break;case 2:ereport(LOG,(errmsg("duration: %s ms statement: %s",msec_str, query_string),errhidestmt(true),errdetail_execute(parsetree_list)));break;}if (save_log_statement_stats)ShowUsage("QUERY STATISTICS");TRACE_POSTGRESQL_QUERY_DONE(query_string);debug_query_string = NULL;
}
check_log_duration函数
可以看到注释中给出了上面case 1,2的含义:
- 1:仅记录duration,即前面提到的两个参数均生效的场景
- 2:记录duration和语句:即前面提到的仅log_min_duration_statement生效的场景
另外是否记录慢sql与 log_duration、log_min_duration_sample 这些参数也有关。
/** check_log_duration* Determine whether current command's duration should be logged* We also check if this statement in this transaction must be logged* (regardless of its duration).** Returns:* 0 if no logging is needed* 1 if just the duration should be logged* 2 if duration and query details should be logged** If logging is needed, the duration in msec is formatted into msec_str[],* which must be a 32-byte buffer.** was_logged should be true if caller already logged query details (this* essentially prevents 2 from being returned).*/
int
check_log_duration(char *msec_str, bool was_logged)
{if (log_duration || log_min_duration_sample >= 0 ||log_min_duration_statement >= 0 || xact_is_sampled){long secs;int usecs;int msecs;bool exceeded_duration;bool exceeded_sample_duration;bool in_sample = false;TimestampDifference(GetCurrentStatementStartTimestamp(),GetCurrentTimestamp(),&secs, &usecs);msecs = usecs / 1000;/** This odd-looking test for log_min_duration_* being exceeded is* designed to avoid integer overflow with very long durations: don't* compute secs * 1000 until we've verified it will fit in int.*/exceeded_duration = (log_min_duration_statement == 0 ||(log_min_duration_statement > 0 &&(secs > log_min_duration_statement / 1000 ||secs * 1000 + msecs >= log_min_duration_statement)));exceeded_sample_duration = (log_min_duration_sample == 0 ||(log_min_duration_sample > 0 &&(secs > log_min_duration_sample / 1000 ||secs * 1000 + msecs >= log_min_duration_sample)));/** Do not log if log_statement_sample_rate = 0. Log a sample if* log_statement_sample_rate <= 1 and avoid unnecessary random() call* if log_statement_sample_rate = 1.*/if (exceeded_sample_duration)in_sample = log_statement_sample_rate != 0 &&(log_statement_sample_rate == 1 ||random() <= log_statement_sample_rate * MAX_RANDOM_VALUE);if (exceeded_duration || in_sample || log_duration || xact_is_sampled){snprintf(msec_str, 32, "%ld.%03d",secs * 1000 + msecs, usecs % 1000);if ((exceeded_duration || in_sample || xact_is_sampled) && !was_logged)return 2;elsereturn 1;}}return 0;
}
参考:
https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-STATEMENT
https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
https://blog.csdn.net/qq_35423190/article/details/129138740
https://iwmj.wordpress.com/2018/04/03/postgresql-%E5%89%8D%E5%90%8E%E7%AB%AF%E5%8D%8F%E8%AE%AE%E4%B8%AD%E7%9A%84%E6%9F%A5%E8%AF%A2%E6%96%B9%E5%BC%8F%EF%BC%9A%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2%E3%80%81%E6%89%A9%E5%B1%95%E6%9F%A5%E8%AF%A2/
相关文章:
PostgreSQL日志中的SQL记录时机 —— log_statement 和 log_min_duration_statement
最近跟朋友讨论到PostgreSQL日志中的SQL记录时机,研究了下log_statement 和 log_min_duration_statement两个参数,记录一下。 一、 参数简介 1. log_statement ① 作用 控制记录SQL的类型,可选值为: none:关闭&…...
Agent举例与应用
什么是Agent OpenAI 应用研究主管 Lilian Weng 在一篇长文中提出了 Agent LLM(大型语言模型)记忆规划技能工具使用这一概念,并详细解释了Agent的每个模块的功能。她对Agent未来的应用前景充满信心,但也表明到挑战无处不在。 现…...
CentOS 7 配置tomcat
简介 Tomcat是一个使用Java编写的开源Web应用服务器,是由Apache Software Foundation管理的一个项目。它是一个轻量级的应用服务器,可以下载、安装和使用,而且还提供了许多高级功能,例如支持Java Servlet、JavaServer Pages (JSP)和JavaServer Faces (JSF) 等JavaEE技术,…...
如何优雅的关闭一个IIS站点
众所周知,当我们使用IIS的时候,在使用负载均衡的情况下,想停掉一个站点,通常会点击Sites(网站)中的Stop(停止)来停止一个站点。但是这样做,会带来一个问题,当…...
弱网模拟工具
一、背景 一个人晚上在家通过 Wi-Fi 上网,在线电影播放基本流畅,可一旦在晚间用网高峰期打视频电话就画面糊,这时不仅可能带宽受限了,还可能有较高的丢包率。与有线网络通信相比,无线网络通信受环境影响会更大&#x…...
Leetcode 第 110 场双周赛 Problem D 2809. 使数组和小于等于 x 的最少时间(DP+贪心+正难则反)
Leetcode 第 110 场双周赛 Problem D 2809. 使数组和小于等于 x 的最少时间(DP 好题)题目 给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒,对于所有下标 0 < i < nums1.length ,nums1[i] 的值都增加 num…...
已知数组A[1..n]中元素类型为非负整数,设计算法将其调整为左右两部分,左边所有为奇数,右边所有为偶数,并要求算法的时间复杂度为O(n)
//左边奇数右边偶数 void Swap(int* a, int* b) {int tmp *b;*b *a;*a tmp; } void LeftRight(int arr[],int n) {int i 0;int j n - 1;while(i<j){if (arr[i] % 2 0 && arr[j] % 2 1) {Swap(&arr[i], &arr[j]);i;j--;}else if (arr[i] % 2 1 &…...
ssm+vue的罪犯信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
演示视频: ssmvue的罪犯信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…...
Java/Android 各类型数据构造和各类型数据解析
Java/Android 各类型数据构造和各类型数据解析 1.如何构造/解析{"key":"value","key":"value","key":"value"}jsonString1)json解析2)fastjson解析3)Gson解析4)遍历key值解析2.如何构造/解析[{"key&q…...
Linux系统---环境变量+内核进程调度队列(选学)
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,…...
Kubernetes 使用插件扩展 kubectl
例子演示 编写 kubectl-foo ,拷贝至 /usr/local/bin/ #!/bin/bash# 可选的参数处理 if [[ "$1" "version" ]] thenecho "1.0.0"exit 0 fi# 可选的参数处理 if [[ "$1" "config" ]] thenecho $KUBECONFIGexit…...
前端面试题09
74、定义类的方法有哪些 在JavaScript中,定义类的方法有以下几种方式: 1.使用函数声明: function MyClass() {// constructor } MyClass.prototype.methodName function() {// method body };2.使用类的方法缩写(ES6引入&…...
网站更换IP的四大注意事项
1.对网站当中的数据进行备份 网站更换IP时可以将页面的数据库文件和站点文件通过下载工具在本地完成备份。 2.更换解析域名 从站点域名管理后台当中更换域名地址,改为新的IP地址。 3.确保IP安全 在用户更换IP前一定要确定IP是否安全,一旦IP存在不良…...
策略模式与简单工厂模式:终结if-else混乱,让代码更清爽
阅读建议 嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议: 本篇文章大概4500多字,预计阅读时间长需要5分钟。本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章&#x…...
TCP三次握手过程
什么是TCP tcp是一个面向连接的、可靠的、基于字节流的传输层通信协议 面向连接:TCP连接是一对一的,不能实现一对多或多对一,TCP在通信前要首先建立连接,连接成功后才能开始进行通信可靠的:TCP连接要保证通信过程的可靠…...
04-配置远程仓库的SSH免密登陆
配置SSH免密登录 配置步骤 创建好的远程仓库也可以使用SSH的方式进行访问,但如果没有配置公钥会有警告 第一步: 删除用户家目录下的.ssh目录,如果没有该目录或者该目录下已经有密钥了就不用执行该操作 #进入当前用户的家目录,删除.ssh 目录 LayneLAPTOP-Layne MINGW64 ~ $ r…...
【中文编码】利用bert-base-chinese中的Tokenizer实现中文编码嵌入
最近接触文本处理,查询了一些资料,记录一下中文文本编码的处理方法吧。 先下载模型和词表:bert-base-chinese镜像下载 如下图示,下载好的以下文件均存放在 bert-base-chinese 文件夹下 1. 词编码嵌入简介 按我通俗的…...
一文解决msxml3.dll文件缺失问题,快速修复msxml3.dll
在了解问题之前,我们必须首先清楚msxml3.dll到底是什么。DLL(Dynamic Link Libraries)文件是Windows操作系统使用的一个重要组成部分,用于存储执行特定操作或任务的代码和数据。msxml3.dll为Windows系统提供处理XML文档的功能。如…...
《React 知识点》第一篇 大括号使用{}
简介 大括号 " {} "可以用于包裹JavaScript的表达式或语句。以便在jsx中动态生成内容。 插入变量与表达式 function expressionTest() {const name "变量测试";return (<p><div>{name}</div><div>表达式 210 {2 100}</div…...
kafka入门(二): 位移提交
位移提交: Kafka的每条消息都有唯一的 offset, 用来表示消息在分区中对应的位置。有的也称之为 “偏移量”。 消费者每次在 poll() 拉取消息,它要返回的是还没有消费过的消息集, 因此,需要记录上一次消费时的消费位…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
