项目地址: 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