21 PostgreSQL 监控2 趋势监控数据收集和分析 nagios 实时监控部署和自定义监控|学习笔记(三)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 快速学习21 PostgreSQL 监控2 趋势监控数据收集和分析 nagios 实时监控部署和自定义监控

开发者学堂课程【PostgreSQL快速入门21 PostgreSQL 监控2 趋势监控数据收集和分析nagios实时监控部署和自定义监控】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/16/detail/80


21 PostgreSQL 监控2 趋势监控数据收集和分析nagios实时监控部署和自定义监控


五、自定义脚本

在编写自定义脚本前首先要搞清楚nagios的判断标准。先来查看规则,例如输入/opt/nagios/libexec/check_load -w 15.10.5 -c 30.25.20

显示结果,再输入 echo $?查看返回值,返回值为0正常

显示结果中的|是将结果信息分为两端,前者为状态,后者为 information。同样我们可以实现此类操作:

1.脚本的返回值

nagios 根据脚本返回值来输出该监控服务的状态.返回值和状态对应关系如下.

0:(OK)

1 : (WARNING)   //告警

2 : (CRITICAL)    //严重告警

other : (UNKNOWN)    //未知状态

image.png

可以看到此时开始监控,有些为正常

2.脚本的标准输出

pg92@db-172-16-3-39-〉/opt/ check_postgres-2.20.0/ check postgres.pl--PGBTNDIR=/opt/pgsql92/bin --output=nagios

--datadir=/pedata1919 --action=checkpoint -w 300s -c 600s

POSTGRES_CHECKPOINT CRTTICAL: Last checkpoint was 11418 seconds ago | age=11418;300;600 //返回值为2,信息分为两段:一个为当前状态,一个为 information

以上监控命令的标准输出为

POSTGRES_CHECKPOINT CRITICAL: Last checkpoint was 11418 seconds ago |age=11418;300:600

被监控机上的脚本是在 nagios 服务端通过 check_nrpe 远程调用的方式执行的.被监控端的nrpe程序以什么用户组执行在如下配置中:

[root@db-172-16-3-39 check_postgres-2.20.0]# cat / etc/xinetd. d/nrpe |grep -E " group|user"

user = pg92

group= pg92

(此处写脚本时使用 postgres 进行调用,如果写其它脚本相当于使用其它用户调用,这个用户必须对脚本有执行权限,否则会报错)

因此监控脚本需要有以上用户组的可执行权限.


六、自写脚本

来自于 bucardo 提供的 check_postgres 脚本。大部分的常用监控项:

是否打开归档(数据库是否开归档很重要,如果开启归档可以做一些备份)

是否打开 vacuum(如果没有自动打开垃圾回收,数据库可能膨胀严重)

数据库年龄

(postgres 使用多版本并行控制,使用32位的一个数据类型,该数据类型很容易达到极限溢出,所以是一个循环使用。例如从0-21循环区间中循环使用,到21后又会返回到0。所以数据库的年龄不允许超过最大值,最大值为2的31次方-当前年龄。例如当前年龄为100万,那么可存活时间为2的31次方-100万。数据库中有很多机制会保护不到达最大年龄,会自动做 vacuum 降低年龄。如果距到达postgre极限还差一百万时不允许在数据库中提交事务,还差一千万时会进行提示及时进行垃圾回收。在数据库中提交事务相当于在消耗年龄。集群为统一的,若数据库中某一个集群的年龄即将到达极限,那么所有集群都将到达极限)

场景:数据库遇到无法正常申请事务号的错误,原因是某些库由于年龄太老,已经到达允许的xid上限(xidStopLimit = xidWrapLimit - 1000000),数据库预留了100万的事务作为维护用.所以此时不允许任何会话申请新的事务号.(如果100万个对象年龄到达极限,那么在降低年龄时需要将100万个对象的年龄都降低。但是在做freeze时,每做一次 freeze,就需要消耗一次事务号,如果对象超过100万,需要消耗超过100万的事务号才能将数据库年龄降低。如果遇到该场景,可以修改源代码,将1000000的值提高,例如将 warnlimit 提高到10000000)

这样的话就必须进入单用户模式做 vacuum freeze 处理.将年龄降下来

另一种情况是警告.如果在到达(xidWarnLimit = xidStopLimit - 10000000)的年龄后,数据库会给出提示,尽快执行vacuum freeze将数据库的年龄降下来,避免达到 xidstopLimit ,那个时候就必须进单用户处理了.

总的来说数据库有几个参数来防止数据库到达 xidStopLimit .

vacuum_freeze_table_age   //指当freeze_table到达指定年龄后,用 vacuum 扫全表

autovacuum_freeze_max_age   //当数据库没有开启 autovacuum 时,只要当表达到限定年龄时会自动做 freeze表进行全表扫描

避免发生数据库年龄到达 xidStopLimit 的几种方法:

(1)合理的设置 vacuum_freeze_table_age,这个参数决定了表的年龄到达这个值以来还未发生过全表数据块的vacuum的话,那么这个 vacuum 或 autovacuum 操作就会扫描全表,并且触发 freeze,从而降低表的年龄.所以这个值不能太大.这样的话数据库有足够多的机会降低表的年龄.但是也不能太小,太小会频繁的触发全表扫,带来 IO 开销.(根据数据库 I/O 情况、数据库事务消耗情况合理设置。例如每天消耗大概一亿的事务,数据库 I/O 允许扫描1G 的表。数据库中最大的表为100G,还有19个事务允许去将表年龄降低。19个亿的事务每天消耗1个亿,相当于19天。即表可以允许用19天时间来降低年龄。)

(2)合理的设置autovacuum_freeze_max_age.这个参数即使在没有开启 autovacuum 的情况下.只要年龄到达这个值也会触发 autovacuum.

这个值是一个比较好的保护值,最大是20亿.但是不建议这么大.应该预留足够的值防止到达 xidStopLimit 和xidWarnLimit 阶段.预留多少合适呢?例如完成全库扫描要1天.并且一天会产生1亿个事务的话,那么预留最少要1亿比较好.这样的话就设置成19亿

(3)数据库的使用要合理.例如对于长事务,并且事务隔离级别是 repeatable read 或 SERIALIZABLE 的话.会影响vacuum freeze 降低对象的年龄(例如有一个存在的事务隔离级别为 repeatable read 或 SERIALIZABLE,那么该事务只要不关闭,vacuum_freeze 不能降低任何表。因为 repeatable read 就确保必须要读到需要的镜像的数据。因此在数据库使用过程中只要是隔离级别的事务,vacuum freeze 不能提前结束该事务,如果在事务结束前就结束了vacuum freeze,那么没有办法降低任何一个表的年龄)

同样要避免和逻辑备份的时间点冲突.逻辑备份使用的是 repeatable read 隔离级别,并且备份时间长

参见:

http://blog.163.com/digoal@126/blog/static/163877040201241134721101/

http://blog.163.com/digoal@126/blog/static/163877040201322510519547/

pg_dump的代码

1、控制单表的大小,因为太大会增加单次扫描的负担.如果未能降低年龄.重复扫描更加浪费(例如 I/O 为每秒100兆,那么单表最好不超过10G。与 I/O 能力有关,如果 I/O 能力强,单表可以大。)

2、提升存储 IO 能力,这样也能提升 VACUUM FREEZE 的速率

3、必要的情况下,进行分库(严格来说是分集群,不要放在一个集群下面.因为xid是整个集群统一分配的)

4、加大maintenance_work_mem,也能一定程度上提升vacuum速率.

数据库单用户模式处理数据库到达 xidStopLimit 场景的方法

首先关闭数据库

然后进入单用户,进入指定的数据库名.

postgres --single -E $dbname

backend>

为了最快的降低数据库的年龄,其实没有必要做全库的 vacuum freeze,数据库的年龄由数据库中年龄最大的表决定:所以只要把年龄最大的表年龄降下来,数据库的年龄就会变成年龄次大的表的年龄,以此类推.

那么我们进入单用户后,首先要按年龄排序,查出年龄大的表-select b.nspnome a.relname, a.relfrozerxid, age (a .relfrozenxid) from pg_class a,pg_namespace b where a.relnanespace=b.oid and a. relkind=' r’ order by a relfrozenari d: : text : : int8 limit 10;

根据查到的表做vacuum freeze.

vacuum freeze tbl;

做完以后,查询一下数据库的年龄是否降了,降到合理范围后(建议降到)

select datname, datfrozexid, age(datfrozenxid) from pg_database ;

然后就可以启动数据库了,启动后建议做全库的 vacuum freeze,彻底降低年龄,同时定制空闲时间的vacuum freeze.

5、连接数

6、提交和回滚的比例(问题修复后.,手工清除统计信息pg_stat_reset(),连接到对应的库执行)

对于数据库如果回滚比例很高,一定程度上说明程序存在问题或者数据库中有逻辑错误导致事务不能提交

7、standby 延迟

通过 replication 对象来监控,sent_location 指对方已经收到的location,pg_current_xlog_insert_location指当前数据库正在写的 location,通过对比两者可以得知 standby 与主库存在多少延迟

8、锁等待

9、长事务/空闲事务

10、prepared 事务

11、序列剩余量(每个库查询)

12、未使用的索引(每个库查询)

一个数据库中对于有频繁删除更新插入的表,索引太多会影响性能,如果索引创建无用,那么还会降低性能,所以监控未使用的索引也是必要的。

以 PostgreSQL9.3为例.脚本如下:

vi nagios. sh

#!/bin/bash

#exp1 : $prog arch   //两种用法,集群级别用法

#exp2 : $prog idx $dbname   //单库使用

# please use database superuser

export LANG=en_US. utf8

export PGPORT=5432  //连接到服务器

export PGDATA=/data01/pgdata/pg_root   //端口号

export PGHDME=/opt/ pgsqlexport LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/ usr/lib84:/usr/local/lib84:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH

export DATE="date +"%Y%m%H%M”’

export PATH=$PGHOME/bin:$PATH:

export PGUSER=postgres  //使用哪个用户连接

export PGHOST=$PGDATA

export PGDATABASE=postgres  //database

#monitor parameter

#cluster monitorarch="select case setting when ' on’then ' Normal ’ else '‘Warning 'end ||name||',' ||setting from pg_settings where

name=' archive_mode’:"   //SQL 语句,通过该语句监控是否打开归档

autovacuum="select case setting when ' on’then ' Nornal ' else ' Warning ’ end||namn||,' ||setting from pg_settings where

name=' autovacuum’;"age="select case when age>600000000 then 'Warning ’ else 'Normal ' end||datname||’age ' ||age from (select  

datname, age(datfrozenxid) as age from pg_database) t order by age ;"  //年龄监控,查 pg_database 字段。设置阈值,>600000000做告警。

conn="select case when t2.setting-t1. cnt < 200 then ' Warning ' else ' Normal ' end||'max ‘||t2. setting||’ now' ||t1. cnt from(select count (*) as cnt from pg_stat_activity)t1, (select setting::int8 from pg_settings where name = ' max_connections')

t2;"   //平均数监控通过查看 pg_stat_activity,查看当前连接在数据库下的连接。max_connections 指数据库允许的最大连接数。此处当剩余连接数<200时warningrollback=select case when xact rollback/xact_comit::.numeric<0.1 then ' Normal ' else 'Warning ' end||datname||’c'||xact_commit||’r ' ||xact_rollback from pg_stat_database where xact_commit>0 order by 1 desc:"   //数据库回滚比例<0.1时正常,>0.1则告警standby="select case when abs>102400 then ‘Warning ' else ' Normal ’ end||' ins '||ins||’ sent '||sent||’ diff '||abs from

(select pg_current_xlog_insert_location() as ins, sent_location assent,abs (pg_xlog location_diff (pg_current_xlog insert_location (), sent_location)) as abs from pg_stat_replication) t:"     //如果使用standby,此处才会有信息,若没有使用则无信息

image.pnglock="select 'Warning ' ||client_addr||’||usename||’'||datname||’‘||query_start ||’‘||now ()||’‘||query from

pg_stat_activity where waiting and now ()-query_start > interval ' 1 min';"  //锁超过1min 则告警xact="select ‘ Warning ' ||client_add||‘||usename||’‘lldatname||’'||xact_start ||’'||now ()||’'||query from

pg_stat_activity where now ()-xact_start > interval ' 1 min ;"   //超过1min 则告警。但是 copy语句肯定超过了1min,如果为拷贝则过滤掉pre_xact="select 'Warning '||transaction||’‘||gid||’'||prepared||’‘||owner||’'||database from pg_prepared_xacts where

now ()-prepared > interval ' 1 min’;"  //超过1min 则告警

#per database monitor

seq="do language plpgsql \$\$

declare

v_seq name ;

v_max int8 := 0;

v_last int8 := 0;

begin

for v_seq in          //序列监控select quote _ident (t2.nspname)|| '.' || quote_ident(t1.relname) from pg_class t1,pg_namespace t2 where

t1.relnamespace=t2.oid and relkind=' S'

loop

execute ' select max_value,last_value from ' ||v_seq into v_max,v_last ;

if v_max-v_last <500000000 then              //序列若不是循环使用,那么剩余小于5亿时告警。可以将序列值往回调,但需要注意序列值不会存在冲突

raise notice 'Warning seq  %last % max %”, v_seq ,v_last,v_max ;

-- else

--raise notice ' Normal seq % last % max %', v_seq v_last, v_max ;

end if;

end loop ;

end;

\$\$;"idx="select 'Warning '||schemaname||’ ‘||relname||''||index_relname||''||idx_scan from pg_ stat_all_indexes whereIdx_scan<10 and schemaname not in ( pg.catalog ,' pg_toast' ) and indexrelid not in (select conindid from pg constraint where

contype in (‘p’ ,'u' )) and pg_relation size (indexrelid)>65536 order by idx scan"

//如果索引大小>60k并且扫描次数<10,认为该索引无用

eval SQL="$"$1

#echo”$SQL"

DB=$2

res= 'psql -q -A -n -t $DB -c "$SQL” 2>&1

if [ $? -eq 0 ]: then

(echo “$res" |grep “Critical" >/dev/null) && echo "$res" && exit 2

(echo “$res" |grep “Warning" >/dev/null) && echo “$res" && exit 1  //脚本结束前进行一些判断:如果找到 Critical 返回2,如果为 Warning,返回1,其它返回0

echo"Sres" ; exit 0

else

echo “$res" ; exit 3   //如果不返回0,则返回3,获取未知状态

fi

chmod 500 nagios. Sh    

使用该脚本后检查输入chmod 500 check_pg.sh

./check_pg.sh arch

./check_pg.sh autovacuum

./check_pg.sh age

皆正常

./check_pg.sh rollback

显示其中一个告警,继续输入 echo $?

返回值为1

再来进行配置

输入#add by digoal

command[check_pg_arch]=/opt/nagios/libexec/check_pg.sh arch

command[check_pg_autovacuum]=/opt/nagios/libexec/check_pg.sh autovacuum

command[check_pg_age]=/opt/nagios/libexec/check_pg.sh age

command[check_pg_conn]=/opt/nagios/libexec/check_pg.sh conn

command[check_pg_rollback]=/opt/nagios/libexec/check_pg.sh rollback

command[check_pg_standby]=/opt/nagios/libexec/check_pg.sh standby

command[check_pg_lock]=/opt/nagios/libexec/check_pg.sh lock

command[check_pg_xact]=/opt/nagios/libexec/check_pg.sh xact

command[check_pg_pre_xact]=/opt/nagios/libexec/check_pg.sh pre_xact

command[check_pg_seq1]=/opt/nagios/libexec/check_pg.sh seq digoal

command[check_pg_seq2]=/opt/nagios/libexec/check_pg.sh seq digoal_01

command[check_pg_seq3]=/opt/nagios/libexec/check_pg.sh  seq test

command[check_pg_idx1]=/opt/nagios/libexec/check_pg.sh idx digoal

command[check_pg_idx2]=/opt/nagios/libexec/check_pg.sh idx digoal_01

command[check_pg_idx3]=/opt/nagios/libexec/check_pg.sh idx test

配置好后进行重启,输入

service xinted restart

重启后需要将以上配置添加到服务中,输入

vi service.cfg

输入

define service<

use generic-service

host_name db_3_33

service_description arch

check_command check_nrpe!check_pg_arch

>

define service<

use generic-service

host_name db_3_33

service_description autovacuum

check_command check_nrpe!check_pg_autovacuum

>

define service<

use generic-service

host_name db_3_33

service_description age

check_command check_nrpe!check_pg_age

>

define service<

use generic-service

host_name db_3_33

service_description conn

check_command check_nrpe!check_pg_conn

>

define service<

use generic-service

host_name db_3_33

service_description rollback

check_command check_nrpe!check_pg_rollback

>

define service<

use generic-service

host_name db_3_33

service_description seq1

check_command check_nrpe!check_pg_seq1

>

define service<

use generic-service

host_name db_3_33

service_description seq2

check_command check_nrpe!check_pg_seq2

>

define service<

use generic-service

host_name db_3_33

service_description idx1

check_command check_nrpe!check_pg_idx1

>

define service<

use generic-service

host_name db_3_33

service_description idx2

check_command check_nrpe!check_pg_idx2

>

演示只添加了部分,添加完后进行重启,输入

service nagios restart

此时再来查看

image.png

可以看到服务很多。此处 total processes 告警,有189个进程

可以调整阀值,进入配置中修改

/opt/nagios/libexec/check_procs -w 250 -c 300

之后输入service xinetd restart

再来查看,可以看到已经正常

image.png

显示为状态信息,如果还需要其它信息,可以使用|分隔开,在输出标准输出时增加一条|即可。

以上就是整个 nagios 服务端、客户端以及自定义脚本如何配置内容。对于自定义脚本存在一个 bucardo 插件,如果了解可以使用进行修改一些内容。不但支持 nagios 还支持其它多种画图工具。

下节讲解第三方插件例如pgstatspack,pg_statsinfo,pgsnap,支持一些图形化的报表输出。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
关系型数据库 Go PostgreSQL
golang pgx自定义PostgreSQL类型
golang的pgx驱动提供了大约70种PostgreSQL类型支持,但还是有一些类型没有涵盖,本文介绍如何自己编写代码支持特殊的类型。
|
关系型数据库 物联网 PostgreSQL
沉浸式学习PostgreSQL|PolarDB 11: 物联网(IoT)、监控系统、应用日志、用户行为记录等场景 - 时序数据高吞吐存取分析
物联网场景, 通常有大量的传感器(例如水质监控、气象监测、新能源汽车上的大量传感器)不断探测最新数据并上报到数据库. 监控系统, 通常也会有采集程序不断的读取被监控指标(例如CPU、网络数据包转发、磁盘的IOPS和BW占用情况、内存的使用率等等), 同时将监控数据上报到数据库. 应用日志、用户行为日志, 也就有同样的特征, 不断产生并上报到数据库. 以上数据具有时序特征, 对数据库的关键能力要求如下: 数据高速写入 高速按时间区间读取和分析, 目的是发现异常, 分析规律. 尽量节省存储空间
782 1
|
3月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
617 2
|
3月前
|
存储 监控 关系型数据库
监控 PostgreSQL 的性能指标
监控 PostgreSQL 的性能指标
175 3
|
5月前
|
SQL 监控 关系型数据库
实时计算 Flink版操作报错合集之在设置监控PostgreSQL数据库时,将wal_level设置为logical,出现一些表更新和删除操作报错,怎么办
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
关系型数据库 定位技术 分布式数据库
沉浸式学习PostgreSQL|PolarDB 18: 通过GIS轨迹相似伴随|时态分析|轨迹驻点识别等技术对拐卖、诱骗场景进行侦查
本文主要教大家怎么用好数据库, 而不是怎么运维管理数据库、怎么开发数据库内核.
1328 1
|
7月前
|
存储 关系型数据库 MySQL
TiDB与MySQL、PostgreSQL等数据库的比较分析
【2月更文挑战第25天】本文将对TiDB、MySQL和PostgreSQL等数据库进行详细的比较分析,探讨它们各自的优势和劣势。TiDB作为一款分布式关系型数据库,在扩展性、并发性能等方面表现突出;MySQL以其易用性和成熟性受到广泛应用;PostgreSQL则在数据完整性、扩展性等方面具有优势。通过对比这些数据库的特点和适用场景,帮助企业更好地选择适合自己业务需求的数据库系统。
1195 4
|
7月前
|
SQL 关系型数据库 MySQL
PostgreSQL【异常 01】java.io.IOException:Tried to send an out-of-range integer as a 2-byte value 分析+解决
PostgreSQL【异常 01】java.io.IOException:Tried to send an out-of-range integer as a 2-byte value 分析+解决
494 1
|
SQL 关系型数据库 MySQL
《PostgreSQL与MySQL:详细对比与分析》
《PostgreSQL与MySQL:详细对比与分析》
644 0
|
人工智能 关系型数据库 Serverless
下一篇
DataWorks