PostgreSQL 可观测性最佳实践

前言

PostgreSQL 介绍

PostgreSQL  是一个高度稳定和功能丰富的开源关系数据库系统。其功能集、扩展性和开源特性使其成为各种类型应用的理想选择,它支持高级特性如事务处理、扩展插件和多种编程语言接口,适用于从 web 应用到企业级系统的各种场景。无论是小型项目还是大型企业级应用 PostgreSQL 都提供可靠、高性能的数据管理解决方案,助力创新和业务增长。

PostgreSQL 核心特性如下:

- SQL 兼容:PostgreSQL 支持大部分 SQL 标准并提供了许多其他先进功能,比如复杂查询、外键、触发器、视图、事务完整性以及多版本并发控制 (MVCC)。

- 扩展性:用户可以通过添加新的数据类型、函数、操作符或者索引方法来扩展 PostgreSQL。

- 高度并发:PostgreSQL 的 MVCC 特性允许数据在读取时不被锁定,从而增加了并发性能和读写操作的效率。

- 多种索引技术:包括 B-tree, hash, GiST, SP-GiST, BRIN 和 GIN 等多种索引技术,使得 PostgreSQL 在不同类型的查询中表现出优异的性能。

- 可靠性和持久性:它支持点对点复制和异步复制以增强数据的安全性和可靠性。

- 程序化:支持多种存储过程语言,如 PL/pgSQL(类似 Oracle 的 PL/SQL)、PL/Python、PL/Perl、PL/Ruby 等。

- JSON 支持:提供对 JSON 数据格式的原生支持,允许直接在数据库中处理 JSON 数据。

使用可观测性工具对 PostgreSQL 数据库进行监控和跟踪至关重要,因为它们提供了对数据库性能、健康状况和运行状况的深入洞察。通过可观测性,数据库管理员和开发人员能够实时检测和诊断问题,从而快速响应并解决潜在的性能瓶颈、查询效率低下或系统错误。此外,可观测性还有助于预测未来的资源需求,优化数据库配置,以及确保数据的安全性和合规性。总之,可观测性是确保 PostgreSQL 数据库稳定、高效运行的关键因素。

观测云介绍

作为一款具备可观测性的统一实时监测应用,观测云可以帮助用户快速实现系统可观测性,统一满足云平台、云原生、应用及业务相关的监测需求,为每一个完整的应用构建全链路的可观测性。观测云数据的采集是通过 DataKit 来实现的,只需要安装 DataKit,开通 PostgreSQL 采集器,即可从 PostgreSQL 实例中采集实例运行状态指标,并将指标采集到观测云,帮助监控分析 PostgreSQL 各种异常情况。以下是安装 DataKit 并开启配置 PostgreSQL 采集器的介绍。

前提条件

部署 DataKit

登录[观测云控制台](https://console.guance.com/),点击「集成」 -「DataKit」 - 「Linux」,复制命令并执行。


PostgreSQL 监控帐号

- PostgreSQL 版本 >= 9.0

- 创建监控帐号

-- PostgreSQL >= 10

create user datakit with password '<PASSWORD>';

grant pg_monitor to datakit;

grant SELECT ON pg_stat_database to datakit;

-- PostgreSQL < 10

create user datakit with password '<PASSWORD>';

grant SELECT ON pg_stat_database to datakit;

操作步骤

指标采集

以下主要是通过主机的方式进行采集,进入 DataKit 安装目录下的 `conf.d/db` 目录,复制 `postgresql.conf.sample` 并命名为 `postgresql.conf`。

注意:address 定义了连接到 postgresql 服务器的 URI,这里的 datakit 是用户名,PASSWORD 应被替换为实际的密码,localhost 是数据库服务器地址,`sslmode=disable` 表示不使用 SSL 连接。

`postgresql_lock` ,`postgresql_stat` ,`postgresql_index` ,`postgresql_size` ,`postgresql_statio` 这些指标需要开启配置文件中的 relations 字段。

[[inputs.postgresql]]

  ## Server address

  # URI format

  # postgres://[datakit[:PASSWORD]]@localhost[/dbname]?sslmode=[disable|verify-ca|verify-full]

  # or simple string

  # host=localhost user=pqgotest password=... sslmode=... dbname=app_production

  address = "postgres://datakit:PASSWORD@localhost?sslmode=disable"

  ## Ignore databases which are gathered. Do not use with 'databases' option.

  #

  # ignored_databases = ["db1"]

  ## Specify the list of the databases to be gathered. Do not use with the 'ignored_databases' option.

  #

  # databases = ["db1"]

  ## Specify the name used as the "server" tag.

  #

  # outputaddress = "db01"

  ## Collect interval

  # Time unit: "ns", "us" (or "µs"), "ms", "s", "m", "h"

  #

  interval = "10s"

  ## Relations config

  # The list of relations/tables can be specified to track per-relation metrics. To collect relation

  # relation_name refer to the name of a relation, either relation_name or relation_regex must be set.

  # relation_regex is a regex rule, only takes effect when relation_name is not set.

  # schemas used for filtering, ignore this field when it is empty

  # relkind can be a list of the following options:

  #  r(ordinary table), i(index), S(sequence), t(TOAST table), p(partitioned table),

  #  m(materialized view), c(composite type), f(foreign table)

  #

[[inputs.postgresql.relations]]

  #relation_name = "products"

  relation_regex = ".*"

  schemas = ["public"]

  relkind = ["r", "p"]

...

日志采集

PostgreSQL 日志输出

PostgreSQL 日志默认是输出至 `stderr` ,如需开启文件日志,可在 PostgreSQL 的配置文件 `/var/lib/pgsql/15/data/postgresql.conf` 调整输出:

logging_collector = on    # 开启日志写入文件功能

log_directory = 'pg_log'  # 设置文件存放目录,绝对路径或相对路径(相对 PGDATA)

log_filename = 'pg.log'  # 日志文件名称

log_statement = 'all'    # 记录所有查询

#log_duration = on

log_line_prefix= '%m [%p] %d [%a] %u [%h] %c ' # 日志行前缀

log_file_mode = 0644

# For Windows

#log_destination = 'eventlog'


PostgreSQL 采集器开启日志采集

PostgreSQL 采集器默认是未开启日志采集功能,可在 `conf.d/db/postgresql.conf` 中将 files 打开,并写入 PostgreSQL 日志文件的绝对路径。在 `[inputs.postgresql.log]` 模块下开启日志采集器配置,如下:

[[inputs.postgresql]]

  ...

  [inputs.postgresql.log]

  files = ["/tmp/pgsql/postgresql.log"]

  multiline_match = '''^\S'''

  auto_multiline_detection = true

  auto_multiline_extra_patterns = []

日志 Pipeline 切割

Pipelines 是一种运行在 DataKit 上的轻量级脚本语言,用于对采集到的数据进行自定义解析和修改。通过定义解析规则,它们能够将不同种类的数据细粒度地切割并转换为结构化的格式,以满足具体的数据管理需求。以下是使用pipeline新建规则对日志原文进行切割的步骤:

在观测云工作空间「日志 > Pipelines」,点击「新建 Pipeline」,在新建 Pipeline 页面,可以先过滤出想要进行文本处理的「数据范围」,然后再定义「解析规则」,若想要测试输入的解析规则是否正确有效,可以在「样本解析」测试输入对应的数据进行测试,测试通过后点击「保存」即可创建 Pipeline 文件。

pipeline 规则:

add_pattern("application_name", "\\[\\w+ \\d+ - DB:\\w+\\]")

grok(_, '%{TIMESTAMP_ISO8601:time} %{NOTSPACE:timezone} \\[%{NOTSPACE:process_id}\\] %{NOTSPACE:db_name} %{application_name:application_name} %{NOTSPACE:user} \\[%{NOTSPACE:localhost}\\] %{NOTSPACE:session_id} ')

default_time(time)      # 将 time 字段作为输出数据的时间戳

日志原文:

2021-05-31 15:23:45.110 CST [74305] test [pgAdmin 4 - DB:postgres] postgres [127.0.0.1] 60b48f01.12241 LOG:  statement:

        SELECT psd.*, 2^31 - age(datfrozenxid) as wraparound, pg_database_size(psd.datname) as pg_database_size

        FROM pg_stat_database psd

        JOIN pg_database pd ON psd.datname = pd.datname

        WHERE psd.datname not ilike 'template%'  AND psd.datname not ilike 'rdsadmin'

        AND psd.datname not ilike 'azure_maintenance'  AND psd.datname not ilike 'postgres'

切割效果:


PostgreSQL 采集器完整配置

# {"version": "1.34.0", "desc": "do NOT edit this line"}

[[inputs.postgresql]]

  ## Server address

  # URI format

  # postgres://[datakit[:PASSWORD]]@localhost[/dbname]?sslmode=[disable|verify-ca|verify-full]

  # or simple string

  # host=localhost user=pqgotest password=... sslmode=... dbname=app_production

  address = "postgres://datakit:datakit@localhost/mydb?sslmode=disable"

  ## Ignore databases which are gathered. Do not use with 'databases' option.

  #

  # ignored_databases = ["db1"]

  ## Specify the list of the databases to be gathered. Do not use with the 'ignored_databases' option.

  #

  # databases = ["db1"]

  ## Specify the name used as the "server" tag.

  #

  # outputaddress = "db01"

  ## Collect interval

  # Time unit: "ns", "us" (or "µs"), "ms", "s", "m", "h"

  #

  interval = "10s"

  ## Relations config

  # The list of relations/tables can be specified to track per-relation metrics. To collect relation

  # relation_name refer to the name of a relation, either relation_name or relation_regex must be set.

  # relation_regex is a regex rule, only takes effect when relation_name is not set.

  # schemas used for filtering, ignore this field when it is empty

  # relkind can be a list of the following options:

  #  r(ordinary table), i(index), S(sequence), t(TOAST table), p(partitioned table),

  #  m(materialized view), c(composite type), f(foreign table)

  #

[[inputs.postgresql.relations]]

  #relation_name = "products"

  relation_regex = ".*"

  schemas = ["public"]

  relkind = ["r", "p"]

  ## Set true to enable election

  election = true

  ## Run a custom SQL query and collect corresponding metrics.

  #

  # [[inputs.postgresql.custom_queries]]

  #  sql = '''

  #    select datname,numbackends,blks_read

  #    from pg_stat_database

  #    limit 10

  #  '''

  #  metric = "postgresql_custom_stat"

  #  tags = ["datname" ]

  #  fields = ["numbackends", "blks_read"]

  ## Log collection

  #

  [inputs.postgresql.log]

  files = ["/var/lib/pgsql/15/data/log/*.log"]

  # pipeline = "postgresql.p"

  multiline_match = '''^\S'''

  auto_multiline_detection = true

  auto_multiline_extra_patterns = []

  ## Custom tags

  #

  [inputs.postgresql.tags]

  server = "pgsql"

  # more_tag = "some_other_value"

  # ...

重启 Datakit

Datakit 配置调整完成后,需要重启才能生效。

datakit service -R

监控视图

登录观测云控制台,点击「场景」 -「新建仪表板」,输入 " PostgreSQL ", 选择" PostgreSQL 监控视图 ",点击"确定"。


关键指标


缓存

通过对 `blks_hit` 和 `blks_read` 这两个关键指标的详细监控和分析,用户可以全面了解 PostgreSQL 数据库的缓存命中率和磁盘 I/O 性能。

- `blks_hit` 指标记录了在 SLRU 缓存中成功命中的磁盘块数量,高的 `blks_hit` 值表示大部分数据请求能够直接从缓存中获取,减少了磁盘 I/O 操作,从而提升了数据库的整体性能和响应速度

- `blks_read` 指标记录了从 SLRU 缓存中未命中时,从磁盘实际读取的磁盘块数量,高的 `blks_read` 值意味着频繁的磁盘读取操作,可能导致响应时间延长和吞吐量下降

事物活动

`xact_commit` 和 `xact_rollback` 这两个关键指标在监控数据库事务活动、评估系统稳定性和优化性能方面有很大作用。

- `xact_commit` 指标记录了在指定时间段内,成功提交到数据库中的事务总数,通过这个指标可以了解业务的吞吐量,评估数据库的使用状况,较高的提交事务数表示数据库正在处理大量的操作

- xact_rollback指标记录了在指定时间段内,因各种原因未能成功提交并被回滚的事务总数。高的回滚次数可能反映出系统存在潜在问题,如应用程序逻辑错误、数据一致性问题或并发事务冲突

死锁

`dealocks` 指标记录了在指定时间段内,数据库中检测到的死锁事件总数,死锁事件的频繁发生会导致部分事务无法完成,进而影响整体数据库的稳定性和可靠性。

行数变动

- `tup_inserted`:插入的行数。

- `tup_updated`:更新的行数。

- `tup_deleted`:删除的行数。

这些指标反映了数据库中新增数据的速率和量级、变更的频率和规模、数据清理的情况和频率,读取的负载和查询效率等。这些指标反映了数据库的操作量,识别哪些业务功能最为活跃,以及业务高峰期的数据库需求,从而进行更精准的资源分配和优化有助于了解业务负载及其对数据库的影响,辅助容量规划和性能优化。

监控器

观测云拥有强大的异常监测能力,不仅提供了包括 Docker、Elasticsearch、Host 等一系列监控模板,还支持自定义监控器。通过监控器配置数据指标检测,从而即时触发告警事件,配合告警通知功能,可及时发现帮助您快速发现问题、定位问题、解决问题。

连接使用率告警

如果 PostgreSQL 连接使用率过高,可能会导致新的连接请求被拒绝,从而影响到应用程序的正常运行。告警可以在连接数接近数据库最大连接数之前,能够采取相应措施,比如增加数据库连接数限制、优化应用程序的连接使用策略或扩展硬件资源,以避免性能瓶颈和潜在的服务中断。


死锁数监控

死锁事件的频繁发生会导致部分事务无法完成,进而影响整体数据库的稳定性和可靠性。


磁盘访问效率告警

使用 `blks_hit` 和 `blks_read` ,我们可以计算缓存命中率,这是衡量缓存效率的一个重要指标。缓存命中率指的是从缓存中获取数据块的操作占所有数据块获取操作(包括从磁盘读取和从缓存获取)的比例。


事物提交/回滚告警

事务提交/回滚率告警和磁盘块访问效率告警,关注数据库事务的健康和数据库读取效率


总结

观测云监控工具为 PostgreSQL 数据库提供全面的性能监控与管理解决方案,能够实时收集和分析关键性能指标和系统日志,可以确保数据库的稳定运行和高效性能。通过整合和分析来自不同来源的数据,观测云使得数据库管理更加智能化和自动化。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容