跳到主要内容
版本:1.6.0

数据库运维

控制面把全部状态保存在一个 PostgreSQL 数据库中,可以是随附的 PostgreSQL 实例,也可以是外部数据库。本文面向该数据库的运维人员,说明哪些数据会增长、需要规划多少磁盘、控制面会自动完成哪些维护,以及需要关注哪些指标。

数据库中大部分是配置数据,体量很小。少数几张表会随流量或时间增长,控制面会定期删除其中的旧数据,无需你执行例行维护任务。

哪些数据会增长,如何受限​

控制面按计划分小批删除旧数据,大多每天一次,首次运行在 cp-api 启动时。删除组织时,控制面还会在后台移除该组织的用量记录、审计事件和通知投递记录。

数据表保留期
用量记录,即 Request Logs 和 Usage 背后的数据dpmgr_usage_events每个组织的用量保留窗口:默认 30 天,可在 1 到 365 天之间调整。参见数据保留。
审计事件audit_eventsaudit.retention_days,默认 730 天。0 表示永久保留。参见审计日志保留。
通知投递记录notification_deliveries90 天。
预算告警记录,用于避免同一预算周期内重复触发告警budget_alert_firings所属预算周期开始后 90 天。
网关上报的配置拒绝记录及其历史dpmgr_rejected_resources、dpmgr_rejected_resources_audit网关最后一次上报该拒绝后 7 天;历史保留 90 天。
网关实例记录dp_nodes网关实例停止发送心跳后约 1 小时。
用量上报回执,用于丢弃网关重复发送的上报dpmgr_usage_batches24 小时。
控制台登录会话auth.console_session过期后 1 天。
配置修订版本kine被取代的修订版本每隔几分钟压缩一次。

只有用量记录的体量与请求量成正比,因此它占据数据库的绝大部分。如需超过组织保留窗口的用量历史,请通过可观测性导出器把用量事件发送到外部存储。

规划容量​

按各组织使用的用量保留期规划数据库容量,默认 30 天,最长 365 天。根据在测试部署上的实测估算,每条用量记录连同索引约占 750 字节。控制面为每次请求尝试写入一条记录,因此发生重试或回退到其他目标的请求会写入多条记录。

存储 ≈ 750 字节 × 每日请求数 × 保留天数,再加上余量

例如,每天处理 1,000,000 个请求、使用默认 30 天保留期的部署大约存储 750 字节 × 1,000,000 × 30 ≈ 23 GB 用量记录。为它们规划约 35 GB,可为重试、两次清理之间的膨胀和流量增长留出空间。再加上审计日志、PostgreSQL 预写日志(WAL)以及回收磁盘空间所需的空闲空间,并在运行几周后用监控查询对照实际表大小校准估算。

例行维护自动完成​

PostgreSQL autovacuum 会回收已删除行占用的空间,供新行复用。由于控制面每天删除旧数据,大表会稳定在某个大小,而不会无限增长。

PostgreSQL 默认的 autovacuum 设置要等表中五分之一的数据发生变化后才触发,对于数千万行的表来说太迟了。控制面在启动时为其大表设置以下表级参数:

autovacuum_vacuum_scale_factor = 0.02
autovacuum_vacuum_insert_scale_factor = 0.02
autovacuum_analyze_scale_factor = 0.01

请勿手动修改这三个参数,控制面会在下次启动时将其恢复。你自行添加的其他表级参数会保持不变。如需查看哪些表带有这些参数,请运行:

SELECT n.nspname AS schema, c.relname AS table_name, c.reloptions
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.reloptions IS NOT NULL
ORDER BY 1, 2;

请保持实例级 autovacuum 开启(autovacuum = on,即 PostgreSQL 默认值),也不要为这些表关闭 autovacuum。autovacuum 关闭时,表级设置不起作用。

回收磁盘空间​

autovacuum 让表内空间可以复用,但不会把空间归还给操作系统。一次性大批量删除后,表文件会保持在峰值大小。例如删除一个大型组织、缩短某个组织的用量保留窗口,或从无限期保留审计事件的版本升级后执行的首次清理。

新数据写入时会复用这些空间,因此只有在必须缩小磁盘占用时才需要回收。稳定运行时通常不需要。最可能需要回收的表是 dpmgr_usage_events、audit_events 和配置存储表 kine。

以下两种方法都会重写整张表,需要大致等于该表当前大小(含索引)的空闲磁盘空间。请先完成备份。

  • pg_repack 在线重写表,只在开始和结束时短暂持有排他锁。如果你的数据库平台提供该扩展(例如 Amazon RDS),可以使用它。控制面本身不需要也不会安装任何扩展,是否安装由你的数据库团队决定。
  • VACUUM FULL 是内置命令,但在完成前会锁住整张表,阻塞读写。请在维护窗口内逐表执行,例如 VACUUM (FULL, ANALYZE) dpmgr_usage_events;。在 dpmgr_usage_events 上执行期间,Request Logs 和 Usage 无法加载,新的用量记录也无法写入。在 kine 上执行期间,配置变更无法下发到网关。

监控数据库​

以下查询均为只读查询。请以控制面的数据库角色,或有权访问统计视图的监控角色运行。

最大的表​

SELECT schemaname, relname,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

dpmgr_usage_events 通常是最大的表。请将其大小与你的容量估算对照。如果某张表在超过其保留期之后仍持续增长,说明删除或 vacuum 没有跟上。

死元组与 autovacuum 活动​

SELECT schemaname, relname, n_live_tup, n_dead_tup,
round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 1) AS dead_pct,
last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

每日清理后,大表上的死元组会短暂上升,autovacuum 应在数小时内清理完毕。如果某张大表的死元组比例持续高于约 10%–20%,或者表仍在写入而 last_autovacuum 已是数天前,就需要排查。常见原因是有东西让旧行保持可见,例如处于事务中却空闲的会话、运行时间很长的查询,或不活跃的复制槽:

SELECT pid, usename, state, now() - xact_start AS transaction_age, left(query, 60) AS query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_start
LIMIT 5;

SELECT slot_name, active, xmin, catalog_xmin FROM pg_replication_slots;

事务 ID 年龄​

SELECT datname, age(datfrozenxid) AS xid_age
FROM pg_database
ORDER BY xid_age DESC;

当旧事务 ID 的年龄达到 autovacuum_freeze_max_age(默认 2 亿)时,PostgreSQL 会对表执行 vacuum 以冻结它们,因此几亿以内的值是正常的。如果年龄持续攀升超过约 5 亿,请用上面的查询找出阻碍 vacuum 的原因。接近 10 亿时应作为紧急情况处理:当年龄接近约 20 亿时,PostgreSQL 会停止接受写入,直到数据库完成 vacuum。

下一步​

如需保护数据库,请参见备份与恢复。审计日志保留设置请参见私有化部署配置。