PostgreSQL ash —— pgsentinel插件

news2024/11/18 6:02:07

一、 插件作用

       众所周知,pg是没有像oracle那样的ash视图的,因此要回溯历史问题不太方便。pgsentinel插件会将pg_stat_activity与pg_stat_statements视图内容定期快照,并存入pg_active_session_history和pg_stat_statements_history视图中。

1. pg_active_session_history视图字段

ColumnType备注
ash_timetimestamp with time zone采样时间
datidoid
datnametext
pidinteger
leader_pidinteger若有并行,其leader进程的pid
usesysidoiduser id
usenametext
application_nametext
client_addrtext
client_hostnametext
client_portinteger
backend_starttimestamp with time zone
xact_starttimestamp with time zone
query_starttimestamp with time zone
state_changetimestamp with time zone
wait_event_typetext
wait_eventtext
statetext
backend_xidxid
backend_xminxid
top_level_querytext执行函数、存储过程时的外层SQL(开pg_stat_statements.track = all才会有区别)
querytext
cmdtypetext

queryidbigint
backend_typetext
blockersintegerblockers数量
blockerpidinteger
blocker_statetext

2. pg_stat_statements_history视图字段

与对应版本的pg_stat_statements视图字段含义相同

ColumnType备注
ash_timetimestamp with time zone
useridoid
dbidoid
queryidbigint
callsbigint
total_exec_timedouble precision
rowsbigint
shared_blks_hitbigint
shared_blks_readbigint
shared_blks_dirtiedbigint
shared_blks_writtenbigint
local_blks_hitbigint
local_blks_readbigint
local_blks_dirtiedbigint
local_blks_writtenbigint
temp_blks_readbigint
temp_blks_writtenbigint
blk_read_timedouble precision
blk_write_timedouble precision
plansbigint
total_plan_timedouble precision
wal_recordsbigint
wal_fpibigint
wal_bytesnumeric

二、 插件安装配置

1. 下载

GitHub - pgsentinel/pgsentinel: postgresql extension providing Active session history

2. 安装

# poatgres用户执行
unzip pgsentinel-master.zip 
cd pgsentinel-master/src
make

# root用户执行(要配环境变量,参考下面)
make install

具体安装过程

-bash-4.2$ unzip pgsentinel-master.zip 
-bash-4.2$ cd pgsentinel-master/src
-bash-4.2$ make
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O2 -fPIC -I. -I./ -I/data/postgres/base/14.0/include/server -I/data/postgres/base/14.0/include/internal  -D_GNU_SOURCE   -c -o pgsentinel.o pgsentinel.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O2 -fPIC -I. -I./ -I/data/postgres/base/14.0/include/server -I/data/postgres/base/14.0/include/internal  -D_GNU_SOURCE   -c -o get_parsedinfo.o get_parsedinfo.c
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O2 -fPIC -shared -o pgsentinel.so pgsentinel.o get_parsedinfo.o -L/data/postgres/base/14.0/lib    -Wl,--as-needed -Wl,-rpath,'/data/postgres/base/14.0/lib',--enable-new-dtags -lm  

[root@linux01 ~]# vi .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
 
export PGHOME=/data/postgres/base/14.0
export PGDATA=/data/postgres/pg5432/data
export PATH=$PGHOME/bin:$PATH:$HOME/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PGHOME/lib
export LANG=en_US.UTF-8                                                  
~                                 
[root@linux01 ~]# source .bash_profile
[root@linux01 ~]# 
[root@linux01 ~]# cd .../pgsentinel-master/src
[root@linux01 src]# make install 
/usr/bin/mkdir -p '/data/postgres/base/14.0/lib'
/usr/bin/mkdir -p '/data/postgres/base/14.0/share/extension'
/usr/bin/mkdir -p '/data/postgres/base/14.0/share/extension'
/usr/bin/install -c -m 755  pgsentinel.so '/data/postgres/base/14.0/lib/pgsentinel.so'
/usr/bin/install -c -m 644 .//pgsentinel.control '/data/postgres/base/14.0/share/extension/'
/usr/bin/install -c -m 644 .//pgsentinel--1.0.sql  '/data/postgres/base/14.0/share/extension/'

创建插件

CREATE EXTENSION pgsentinel;

3. 插件配置

  • 必须配置
vi postgresql.conf
shared_preload_libraries = 'pg_stat_statements,auto_explain,pgsentinel'

若未配置,查询会报错

postgres=# select * from pg_active_session_history ; 
ERROR:  pg_active_session_history must be loaded via shared_preload_libraries

重启db生效

pg_ctl stop -m fast
pg_ctl start -D $PGDATA

postgres=# select * from pg_active_session_history ;
(0 rows)

  • 可选配置

也可以直接在postgresql.conf中修改

参数名Description默认值建议值
pgsentinel_ash.sampling_period采样时间(秒)110(高负载)
pgsentinel_ash.max_entriespg_active_session_history视图在内存中的缓冲区大小(字节)100010000
pgsentinel.db_name数据存在哪个db中postgrespgawr
pgsentinel_ash.track_idle_trans是否记录 idle in transaction 状态会话falsetrue
pgsentinel_pgssh.max_entriespg_stat_statements_history 视图在内存中的缓冲区大小(字节)1000010000
pgsentinel_pgssh.enable启用 pg_stat_statements_historyfalsetrue

这部分对应源码

/* GUC variables */
static int ash_sampling_period = 1;
static int ash_max_entries = 1000;
static int pgssh_max_entries = 10000;
static bool pgssh_enable = false;
static bool ash_track_idle_trans = false;
static int ash_restart_wait_time = 2;
char *pgsentinelDbName = "postgres";

  • 其他相关参数

查询语句保留长度

# 为每个活动会话的pg_stat_activity.query字段所保留的内存量(字节,默认1024)
track_activity_query_size = 2048

跟踪层级

       pgsentinel依赖于pg_stat_statements插件的数据,如果想要更详细,可以调整相应参数(但必须注意对系统的负载)

# 记录函数和存储过程中的子语句
pg_stat_statements.track = all

四、 实现原理

       插件最核心的就是pg_active_session_history,pg_stat_statements_history两个视图,所以源码中最重要的,也就是这两个视图的创建。

1. 视图创建

源码中的 pgsentinel--1.0.sql,可以看到这两个视图内容来自两个函数,并进行授权

CREATE VIEW pg_active_session_history AS
  SELECT * FROM pg_active_session_history();

GRANT SELECT ON pg_active_session_history TO PUBLIC;
  
CREATE VIEW pg_stat_statements_history AS
  SELECT * FROM pg_stat_statements_history();

GRANT SELECT ON pg_stat_statements_history TO PUBLIC;

而这两个函数实际是用c语言编写的

2. 函数创建


CREATE FUNCTION pg_active_session_history(
    OUT ash_time timestamptz,
    OUT datid Oid,
    OUT datname text,
    OUT pid integer,
    OUT leader_pid integer,
    OUT usesysid Oid,
    OUT usename text,
    OUT application_name text,
    OUT client_addr text,
    OUT client_hostname text,
    OUT client_port integer,
    OUT backend_start timestamptz,
    OUT xact_start timestamptz,
    OUT query_start timestamptz,
    OUT state_change timestamptz,
    OUT wait_event_type text,
    OUT wait_event text,
    OUT state text,
    OUT backend_xid xid,
    OUT backend_xmin xid,
    OUT top_level_query text,
    OUT query text,
    OUT cmdtype text,
    OUT queryid bigint,
    OUT backend_type text,
    OUT blockers integer,
    OUT blockerpid integer,
    OUT blocker_state text
)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pg_active_session_history'
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;

-- Register a view on the function for ease of use.
CREATE VIEW pg_active_session_history AS
  SELECT * FROM pg_active_session_history();

GRANT SELECT ON pg_active_session_history TO PUBLIC;

CREATE FUNCTION pg_stat_statements_history(
    OUT ash_time timestamptz,
    OUT userid Oid,
    OUT dbid Oid,
    OUT queryid bigint,
    OUT calls bigint,
    OUT total_exec_time double precision,
    OUT rows bigint,
    OUT shared_blks_hit bigint,
    OUT shared_blks_read bigint,
    OUT shared_blks_dirtied bigint,
    OUT shared_blks_written bigint,
    OUT local_blks_hit bigint,
    OUT local_blks_read bigint,
    OUT local_blks_dirtied bigint,
    OUT local_blks_written bigint,
    OUT temp_blks_read bigint,
    OUT temp_blks_written bigint,
    OUT blk_read_time double precision,
    OUT blk_write_time double precision,
	OUT plans bigint,
	OUT total_plan_time double precision,
	OUT wal_records bigint,
	OUT wal_fpi bigint,
	OUT wal_bytes numeric
)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pg_stat_statements_history'
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;

既然如此,我们看看源码中究竟是怎么实现的这些函数


五、 源码学习

1. pg_active_session_history函数内容

它有两个分支,另外根据不同pg版本有不同语句(这里只挑了一个版本):

  • 启用pgsa_query_no_track_idle,即只记录active会话
select act.datid, act.datname, act.pid, act.usesysid, act.usename, \
 act.application_name, text(act.client_addr), act.client_hostname, \
 act.client_port, act.backend_start, act.xact_start, act.query_start,  \
 act.state_change, case when act.wait_event_type is null then 'CPU' \
 else act.wait_event_type end as wait_event_type,case when act.wait_event is null \
 then 'CPU' else act.wait_event end as wait_event, act.state, act.backend_xid, \
 act.backend_xmin, act.query, act.backend_type,(pg_blocking_pids(act.pid))[1], \
 cardinality(pg_blocking_pids(act.pid)),blk.state,gpi.*, act.leader_pid \
 from pg_stat_activity act left join pg_stat_activity blk  \
 on (pg_blocking_pids(act.pid))[1] = blk.pid,get_parsedinfo(act.pid) gpi \
 where act.state ='active' and act.pid != pg_backend_pid()";
  • 启用 pgsa_query_track_idle,即记录active和idle in transaction会话
select act.datid, act.datname, act.pid, act.usesysid, act.usename, \
 act.application_name, text(act.client_addr), act.client_hostname, \
 act.client_port, act.backend_start, act.xact_start, act.query_start,  \
 act.state_change, case when act.wait_event_type is null then 'CPU' \
 else act.wait_event_type end as wait_event_type,case when act.wait_event is null \
 then 'CPU' else act.wait_event end as wait_event, act.state, act.backend_xid, \
 act.backend_xmin, act.query, act.backend_type,(pg_blocking_pids(act.pid))[1], \
 cardinality(pg_blocking_pids(act.pid)),blk.state,gpi.*, act.leader_pid \
 from pg_stat_activity act left join pg_stat_activity blk  \
 on (pg_blocking_pids(act.pid))[1] = blk.pid,get_parsedinfo(act.pid) gpi \
 where act.state in ('active', 'idle in transaction') and act.pid != pg_backend_pid()";

2. pg_stat_statements_query函数内容

也有版本区分,这里只取其中一版

 select userid, dbid, queryid, calls, total_exec_time, rows, shared_blks_hit, \
 shared_blks_read, shared_blks_dirtied, shared_blks_written, local_blks_hit, \
 local_blks_read, local_blks_dirtied, local_blks_written, temp_blks_read, \
 temp_blks_written, blk_read_time, blk_write_time, \
 plans, total_plan_time, wal_records, wal_fpi, wal_bytes \
 from pg_stat_statements \
 where queryid in  (select queryid from pg_active_session_history  \
 where ash_time in (select ash_time from pg_active_session_history  \
 order by ash_time desc limit 1))";

3. 记录内容

每一行记录叫做一个entry

  • pg_active_session_history对应叫ashEntry
  • pg_stat_statements_query对应叫pgsshEntry
/* ash entry */
typedef struct ashEntry
{
	int pid;
#if PG_VERSION_NUM >= 130000
	int leader_pid;
#endif
	int client_port;
	uint64 queryid;
	TimestampTz ash_time;
	Oid datid;
	Oid usesysid;
	char *usename;
	char *datname;
	char *application_name;
	char *wait_event_type;
	char *wait_event;
	char *state;
	char *blocker_state;
	char *client_hostname;
	int blockers;
	int blockerpid;
	char *top_level_query;
	char *query;
	char *cmdtype;
	char *backend_type;
	char *client_addr;
	TransactionId backend_xmin;
	TransactionId backend_xid;
	TimestampTz backend_start;
	TimestampTz xact_start;
	TimestampTz query_start;
	TimestampTz state_change;
} ashEntry;

/* pg_stat_statement_history entry */
typedef struct pgsshEntry
{
	TimestampTz ash_time;
	Oid userid;
	Oid dbid;
	uint64 queryid;
	int64 calls;
	double total_time;
	int64 rows;
	int64 shared_blks_hit;
	int64 shared_blks_read;
	int64 shared_blks_dirtied;
	int64 shared_blks_written;
	int64 local_blks_hit;
	int64 local_blks_read;
	int64 local_blks_dirtied;
	int64 local_blks_written;
	int64 temp_blks_read;
	int64 temp_blks_written;
	double blk_read_time;
	double blk_write_time;
#if PG_VERSION_NUM >= 130000
	int64 plans;
	double total_plan_time;
	int64 wal_records;
	int64 wal_fpi;
	uint64 wal_bytes;
#endif
} pgsshEntry; 

每个字段有一个buffer变量,记录共享内存用量,例如

static char *AshEntryUsenameBuffer = NULL;
static char *AshEntryDatnameBuffer = NULL;
static char *AshEntryAppnameBuffer = NULL;

ash_entry_memsize和pgssh_entry_memsize估算entry所需内存

参考:

GitHub - pgsentinel/pgsentinel: postgresql extension providing Active session history

一种PostgreSQL数据库监控和溯源分析的方法和系统与流程

PostgreSQL 12.2官方手册学习( 第19章 运行时统计数据) - 墨天轮

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1063002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【实操记录】Oracle数据整库同步至Apache Doris

本文是Oracle数据整库同步至Apache Doris实操记录,仅供参考 参考:https://cn.selectdb.com/blog/104 1、Oracle 配置 [rootnode1 oracle]# pwd /u01/app/oracle [rootnode1 oracle]# mkdir recovery_area [rootnode1 oracle]# chown -R oracle:dba re…

WPF中, 如何将控件的触发事件绑定到ViewModel

在DataGrid 等控件中, 有很多这种带闪电符号的触发事件. 如果用传统的事件驱动, 则直接在后台中建立 一个private PropertyChanged(Sender s, EventAgars Args) 即可. 但是如果需要绑定到ViewModel的话? 应该怎么做? 带闪电符号的触发事件 实现viewModel绑定前端触发事件的…

【C++设计模式之原型模式:创建型】分析及示例

简介 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有对象来生成新的对象,而无需再次使用构造函数。 描述 原型模式通过复制现有对象来创建新的对象,而无需显式地调用构造函数或暴露对象的创建…

JAVA编程题-求矩阵螺旋值

螺旋类 package entity; /*** 打印数组螺旋值类*/ public class Spiral { // 数组行private int row; // 数组列private int col; // 行列数private int size; // 当前行索引private int rowIndex; // 当前列索引private int colIndex; // 行开始索引private int rowStart; //…

大模型部署手记(5)ChatGLM2+Jetson AGX Orin

1.简介: 组织机构:智谱/清华 代码仓:https://github.com/THUDM/ChatGLM2-6B 模型:THUDM/chatglm2-6b 下载:https://huggingface.co/THUDM/chatglm2-6b 镜像下载:https://aliendao.cn/models/THUDM/chat…

Java日期的学习篇

关于日期的学习 目录 关于日期的学习JDK8以前的APIDate Date常用APIDate的API应用 SimpleDateFormatSimpleDateFormat常用API测试 反向格式化(逆操作)测试 训练案例需求(秒杀活动)实现 Calendar需求痛点常见API应用测试 JDK8及以后的API(修改与新增)为啥学习(推荐使用)新增的AP…

ArcGIS Engine:鹰眼图的拓展功能-点击和矩形+坐标状态栏

目录 01 前言 02 鹰眼图的控制功能 03 显示当前鼠标的地理坐标 01 前言 说是拓展,不过是忘记了实验还有附加实验.这里补上. 前文不再赘述,上一节查看:ArcGIS Engine:视图菜单的创建和鹰眼图的实现_炒茄子的博客-CSDN博客 这里加上三个功能…

unity脚本_Vector3 c#

接下来学习 相对世界坐标 首先我们给场景物体一个空物体 修改新建空物体名字为GameObjectFather 修改GameObjectFather坐标 修改GameObject2坐标 然后将GameObjectFahter设置成GameObject2的父物体 我们观察到子物体的坐标改变了但是 运行显示的相对世界坐标this.transform.po…

R语言教程课后习题答案(持续更新中~~)

R语言教程网址如下 https://www.math.pku.edu.cn/teachers/lidf/docs/Rbook/html/_Rbook/index.html 目录 source()函数可以运行保存在一个文本文件中的源程序 R向量下标和子集 数值型向量及其运算 日期功能 R因子类型 source()函数可以运行保存在一个文本文件中的源程序…

学信息系统项目管理师第4版系列18_采购管理

1. 协议 1.1. 合同 1.1.1. 国际合作的项目经理应牢记,无论合同规定如何详尽,文化和当地法律对合同及其可执行性均有影响 1.2. 服务水平协议(SLA) 1.3. 谅解备忘录 1.4. 协议备忘录(MOA) 1.5. 订购单 …

十天学完基础数据结构-第八天(哈希表(Hash Table))

哈希表的基本概念 哈希表是一种数据结构,用于存储键值对。它的核心思想是将键通过哈希函数转化为索引,然后将值存储在该索引位置的数据结构中。 哈希函数的作用 哈希函数是哈希表的关键部分。它将输入(键)映射到哈希表的索引位…

Python常用功能的标准代码

后台运行并保存log 1 2 3 4 5 6 7 8 9 nohup python -u test.py > test.log 2>&1 & #最后的&表示后台运行 #2 输出错误信息到提示符窗口 #1 表示输出信息到提示符窗口, 1前面的&注意添加, 否则还会创建一个名为1的文件 #最后会把日志文件输出到test.log文…

卷积神经网络-池化层和激活层

2.池化层 根据特征图上的局部统计信息进行下采样,在保留有用信息的同时减少特征图的大小。和卷积层不同的是,池化层不包含需要学习的参数。最大池化(max-pooling)在一个局部区域选最大值作为输出,而平均池化(average pooling)计算一个局部区…

卷积神经网络-卷积层

卷积神经网络 卷积神经网络(convolutional neural network,CNN)是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之一。卷积神经网络具有表征学习能力,能够按其阶层结构对输入信息进行平移不变分…

H5移动端购物商城系统源码 小型商城全新简洁风格全新UI 支持易支付接口

一款比较简单的 H5 移动端购物商城系统源码,比较适合单品商城、小型商城使用。带有易支付接口。 源码下载:https://download.csdn.net/download/m0_66047725/88391704 源码下载2:评论留言或私信留言

【Spring笔记03】Spring依赖注入各种数据类型

这篇文章,详细介绍一下Spring框架中如何注入各种数据类型,包含:注入基本数据类型、数组、集合、Map映射、Property属性、注入空字符串、注入null值、注入特殊字符等内容,以及如何使用命名空间进行依赖注入。 目录 一、注入各种数据…

云原生Kubernetes:简化K8S应用部署工具Helm

目录 一、理论 1.HELM 2.部署HELM2 3.部署HELM3 二、实验 1.部署 HELM2 2.部署HELM3 三、问题 1.api版本过期 2.helm初始化报错 3.pod状态为ImagePullBackOff 4.helm 命令显示 no repositories to show 的错误 5.Helm安装报错 6.git命令报错 7.CentOS 7 下git c…

互联网Java工程师面试题·Elasticsearch 篇·第一弹

目录 1、elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段 。 1.1 设计阶段调优 1.2 写入调优 1.3 查询调优 1.4 其他调优 2、elasticsearch 的倒排索引是什么 3、elastic…

ToDoList使用自定义事件传值

MyTop与MyFooter与App之间传递数据涉及到的就是子给父传递数据,MyList和MyItem与App涉及到爷孙传递数据。 之前的MyTop是使用props接收App传值,然后再在methods里面调用,现在使用自定义事件来处理子组件和父组件之间传递数据。 图是之前的…

新款UI动态壁纸头像潮图小程序源码

新款UI动态壁纸头像潮图小程序源码,不需要域名服务器,直接添加合法域名,上传发布就能使用。 可以对接开通流量主,个人也能运营,不需要服务器源码完整。整合头像,动态壁纸,文案功能齐全。 源码…