postgres-checkup PG体检工具

2022-04-18 14:22:35 浏览数 (1)

项目地址: https://gitlab.com/postgres-ai/postgres-checkup

Postgres Checkup (postgres-checkup) 是一种新型的诊断工具,用于深入分析 Postgres 数据库的健康状况。它检测数据库性能、可扩展性和安全性方面的当前和潜在问题。它还就如何解决或预防这些问题提出建议。

监控系统只会显示当前紧迫的问题。并且 postgres-checkup 将显示潜行的、更深层次的问题,这些问题可能会在未来打击你。它有助于解决许多已知的数据库管理问题和常见的陷阱。它旨在及早发现问题并提出预防问题的最佳方法。我们建议定期运行它们——每周、每月和每季度。并且在对数据库服务器应用任何重大更改之前和之后运行这些。无论是架构或配置参数还是集群设置更改。

1 它不引人注目:它对观测系统的影响接近于零。它不使用任何繁重的查询,保持资源使用率非常低,并避免产生“观察者效应”。 postgres-checkup 报告已在包含 500,000 多个表和 1,000,000 多个索引的真实数据库上成功测试。

2 零安装(在观察到的机器上):它能够分析任何 Linux 机器(包括虚拟机)以及云 Postgres 实例(如 Amazon RD 或 Google Cloud SQL),无需任何额外设置或任何更改。但是,它确实需要 DBA 通常拥有的特权访问权限。

3 复杂分析:与大多数仅提供原始数据的监控工具不同,postgres-checkup 结合了来自系统各个部分的数据(例如,内部 Postgres 统计信息与 autovacuum 设置和行为分析中有关系统资源的知识相结合)将数据加入到井中格式的报告旨在解决特定的 DBA 问题。此外,它还会分析主数据库服务器及其所有副本,这在索引分析或搜索设置偏差等情况下是必要的。

postgres-checkup 支持通过ssh连接到远程PG上执行采集,也支持通过pg连接进行采集。

因为生产环境下可能不容易让我们把pg的机器做ssh打通,因此下面的演示中,我只要在采集机器上安装相关的包即可,主要操作是通过psql去连接远程的pg数据库采集数据的。

采集机器上需要具备的环境:

代码语言:javascript复制
采集机器上需要具备的环境:
bash
psql
coreutils
jq >= 1.5
go >= 1.17 (no binaries are shipped at the moment)
awk
sed
pandoc   # 如果要输出为html或pdf格式,则需要安装这个包
wkhtmltopdf >= 0.12.4  # 如果要输出为html或pdf格式,则需要安装这个包

1 安装依赖包

代码语言:javascript复制
yum install git postgresql coreutils jq golang  # 如果已经安装过或者编译安装过,这里就不用yum二次安装了

2 编译代码

代码语言:javascript复制
git clone https://gitlab.com/postgres-ai/postgres-checkup.git
# Use --branch to use specific release version. For example, to use version 1.1:
#   git clone --branch 1.1 https://gitlab.com/postgres-ai/postgres-checkup.git

如果下载包比较慢的话,可以直接下载tar.gz包,我这里用的是下载好的tar.gz包

cd postgres-checkup-master

cd ./pghrep
make main
cd ..

注意, checkup是按照database维度生成的报告,因此有多个库的话,需要采集多次!

3 生成markdown文档(默认格式就是markdown)

代码语言:javascript复制
$ export PGPASSWORD='dts'
$ ./checkup -h 192.168.31.181 -p 1921  --username dts --dbname postgres --project prod1 -e 1

或者明确使用pg的连接方式
./checkup --pg-hostname 192.168.31.181 --pg-port 1921 --username dts --dbname mydatabase --connection-timeout 5 --statement-timeout 10 --project prod_app1 -e 1

4 生成html文档(可选,html的结果放到邮件里面更方便查看)

代码语言:javascript复制
如果要生成html文档,需要先安装相关依赖包

# Optional (to generate PDF/HTML reports)
sudo yum install -y pandoc
wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
tar xvf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
sudo mv wkhtmltox/bin/wkhtmlto* /usr/local/bin
sudo yum install -y libpng libjpeg openssl icu libX11 libXext libXrender xorg-x11-fonts-Type1 xorg-x11-fonts-75dpi
代码语言:javascript复制
$ export PGPASSWORD='dts'
$ ./checkup -h 192.168.31.181 -p 1921  --username dts --dbname postgres --project prod1 -e 1 --html

或者明确使用pg的连接方式
./checkup --pg-hostname 192.168.31.181 --pg-port 1921 --username dts --dbname mydatabase --connection-timeout 5 --statement-timeout 10 --project prod_app1 -e 1 --html

因为我们这里没有用ssh方式探测,因此在运行日志里面有些报错,但是基本对指标采集上无影响(有些生产场景下,也不允许随意将db机器和其它节点进行ssh打通)

代码语言:javascript复制
部分日志如下:
[2022-04-17T20:09:00 0800] Сonnection type (specified): PostgreSQL (192.168.31.181:1921)
[2022-04-17T20:09:00 0800] 
[2022-04-17T20:09:00 0800] ########## Perform checks for host '192.168.31.181':
[2022-04-17T20:09:00 0800] 
[2022-04-17T20:09:00 0800] === Run on '192.168.31.181': ./resources/checks/A001_system_info.sh ===
SSH is not supported, skipping...
[2022-04-17T20:09:00 0800] === End of running ===
[2022-04-17T20:09:00 0800] WARNING: check 'A001' failed with error ^^^
[2022-04-17T20:09:00 0800] 
省略部分
[2022-04-17T20:09:54 0800] K000: markdown reports saved at:
[2022-04-17T20:09:54 0800] './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/K001.md'
[2022-04-17T20:09:54 0800] './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/K002.md'
[2022-04-17T20:09:54 0800] './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/K003.md'
[2022-04-17T20:09:55 0800] L001: markdown report saved at: './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/L001.md'
[2022-04-17T20:09:55 0800] L003: markdown report saved at: './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/L003.md'
[2022-04-17T20:10:01 0800] 
[2022-04-17T20:10:01 0800] Final .md report is ready at:
        './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/0_Full_report.md'
[2022-04-17T20:10:01 0800] 
[2022-04-17T20:10:03 0800] Final .html report is ready at:
        './artifacts/prod_app1/md_reports/1_2022_04_17T12_52_08_ 0800/0_Full_report.html'
[2022-04-17T20:10:03 0800]
[2022-04-17T20:10:03 0800] ALL DONE!

注意事项1,一些报告(例如 K003)需要两个快照,以计算指标的“增量”。因此,为了获得更好的结果,请使用以下示例,在高峰工作时间执行它,$DISTANCE 值从 10 分钟到几个小时:

代码语言:javascript复制
# 下面这种通过增量采集的,可以捕获到top0-50 query等指标信息
$DISTANCE="1800" # 30 minutes

export PGPASSWORD='xxxx'

# 假设主节点master.pg.demo.com,还有2个从节点standby1.pg.demo.com 和 standby2.pg.demo.com
for host in master.pg.demo.com standby1.pg.demo.com standby2.pg.demo.com ; do
  ./checkup 
    -h "$host" 
    -p 5432 
    --username postgres 
    --dbname postgres 
    --project prod1 
    -e 1 
    --file resources/checks/K000_query_analysis.sh   # the first snapshot is needed only for reports K***
done

sleep "$DISTANCE"

for host in master.pg.demo.com standby1.pg.demo.com standby2.pg.demo.com ; do
  ./checkup 
    -h "$host" 
    -p 5432 
    --username postgres 
    --dbname postgres 
    --project prod1 
    -e 1
done

使用增量采集后,采集结果中,会多出一项 K003 Top-50 Queries by total_time ,如下图:

注意事项2,我在执行checkup命令时候,有提示如下报错:

代码语言:javascript复制
[2022-04-17T12:52:20 0800] === Run on '192.168.31.181': ./resources/checks/K000_query_analysis.sh ===
psql:<stdin>:45: ERROR:  column "total_time" does not exist
LINE 9:       total_time,
              ^
ERROR: To compare results, 2 runs are needed. Please run './checkup collect' once again for this epoch.
NOTICE: ^^ this is not a real error. Just run check again.
[2022-04-17T12:52:21 0800] === End of running ===
[2022-04-17T12:52:21 0800] WARNING: check 'K000' failed with error ^^^

看起来是某个sql问题,对比下看pg_stat_statements的列和sql里面的列的差异,发现是其中一个列不一致导致的:

代码语言:javascript复制
=# dx pg_stat_statements
                                          List of installed extensions
        Name        │ Version │ Schema │                              Description                               
────────────────────┼─────────┼────────┼────────────────────────────────────────────────────────────────────────
 pg_stat_statements │ 1.9     │ public │ track planning and execution statistics of all SQL statements executed
(1 row)

=# d pg_stat_statements
                    View "public.pg_stat_statements"
       Column        │       Type       │ Collation │ Nullable │ Default 
─────────────────────┼──────────────────┼───────────┼──────────┼─────────
 userid              │ oid              │           │          │ 
 dbid                │ oid              │           │          │ 
 toplevel            │ boolean          │           │          │ 
 queryid             │ bigint           │           │          │ 
 query               │ text             │           │          │ 
 plans               │ bigint           │           │          │ 
 total_plan_time     │ double precision │           │          │ 
 min_plan_time       │ double precision │           │          │ 
 max_plan_time       │ double precision │           │          │ 
 mean_plan_time      │ double precision │           │          │ 
 stddev_plan_time    │ double precision │           │          │ 
 calls               │ bigint           │           │          │ 
 total_exec_time     │ double precision │           │          │ 
 min_exec_time       │ double precision │           │          │ 
 max_exec_time       │ double precision │           │          │ 
 mean_exec_time      │ double precision │           │          │ 
 stddev_exec_time    │ double precision │           │          │ 
 rows                │ bigint           │           │          │ 
 shared_blks_hit     │ bigint           │           │          │ 
 shared_blks_read    │ bigint           │           │          │ 
 shared_blks_dirtied │ bigint           │           │          │ 
 shared_blks_written │ bigint           │           │          │ 
 local_blks_hit      │ bigint           │           │          │ 
 local_blks_read     │ bigint           │           │          │ 
 local_blks_dirtied  │ bigint           │           │          │ 
 local_blks_written  │ bigint           │           │          │ 
 temp_blks_read      │ bigint           │           │          │ 
 temp_blks_written   │ bigint           │           │          │ 
 blk_read_time       │ double precision │           │          │ 
 blk_write_time      │ double precision │           │          │ 
 wal_records         │ bigint           │           │          │ 
 wal_fpi             │ bigint           │           │          │ 
 wal_bytes           │ numeric          │           │          │ 

脚本里面写的是 total_time ,在pg_stat_statements 1.9版本里面改为了 total_exec_time,我们改下脚本就可以了:

代码语言:javascript复制
sed -i.bak 's#total_time#total_exec_time#g' ./resources/checks/K000_query_analysis.sh 

部署到生产的话,还有很多要完善的地方。例如先将库先提取出来,然后逐个进行检测。

代码语言:javascript复制
# 还没完善,还需要加上不同集群的各实例的定期检测,并将结果定期邮件发出的功能

export PGPASSWORD='dts'

db_arry=$(echo "select datname from pg_database where datname not in ('template1','template0');" |psql -h 192.168.31.181 -p 1921 -Xqt --csv)
echo $db_arry

for dbname in ${db_arry} ; do
  ./checkup -h 192.168.31.181 -p 1921  --username dts --dbname ${dbname} --project prod_instance1_${dbname} -e 1 --html 
done

0 人点赞