Skip to content

PostgreSQL 连接数告警

连接数监控配置

1. 使用内置视图监控连接数

sql
-- 查看当前连接数统计
SELECT 
    datname, 
    usename, 
    application_name, 
    state, 
    count(*) AS connection_count
FROM 
    pg_stat_activity
GROUP BY 
    datname, usename, application_name, state
ORDER BY 
    connection_count DESC;

-- 查看总连接数和使用率
SELECT 
    current_setting('max_connections')::int AS max_connections,
    COUNT(*) AS current_connections,
    ROUND(COUNT(*) * 100.0 / current_setting('max_connections')::int, 2) AS connection_usage_percent
FROM 
    pg_stat_activity;

-- 查看空闲连接超过5分钟的连接
SELECT 
    pid, 
    datname, 
    usename, 
    application_name, 
    client_addr, 
    backend_start, 
    state_change
FROM 
    pg_stat_activity
WHERE 
    state = 'idle' 
    AND state_change < NOW() - INTERVAL '5 minutes';

2. 使用 Prometheus 监控连接数

配置 Prometheus 抓取 PostgreSQL 连接数指标:

yaml
# prometheus.yml 配置示例
scrape_configs:
  - job_name: 'postgresql'
    static_configs:
      - targets: ['postgres-exporter:9187']
    metrics_path: /metrics
    scrape_interval: 15s

常用的 PostgreSQL 连接数指标:

  • pg_stat_database_numbackends:每个数据库的连接数
  • pg_settings_max_connections:最大连接数配置
  • pg_stat_activity_count_by_state:按状态分类的连接数

连接数告警配置

1. 使用 Prometheus Alertmanager 配置告警

yaml
# 连接数告警规则示例
groups:
- name: postgresql_connection_alerts
  rules:
  - alert: PostgreSQLHighConnectionUsage
    expr: pg_stat_database_numbackends / pg_settings_max_connections > 0.8
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "PostgreSQL 连接使用率过高"
      description: "数据库 {{ $labels.datname }} 连接使用率超过 80%,当前值: {{ $value | printf "%.2f" }}%"

  - alert: PostgreSQLCriticalConnectionUsage
    expr: pg_stat_database_numbackends / pg_settings_max_connections > 0.95
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "PostgreSQL 连接使用率严重过高"
      description: "数据库 {{ $labels.datname }} 连接使用率超过 95%,当前值: {{ $value | printf "%.2f" }}%"

  - alert: PostgreSQLTooManyIdleConnections
    expr: sum by (datname) (pg_stat_activity_count_by_state{state="idle"}) > 50
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "PostgreSQL 空闲连接过多"
      description: "数据库 {{ $labels.datname }} 空闲连接数超过 50,当前值: {{ $value }}"

2. 使用脚本监控和告警

创建连接数监控脚本 check_connection_count.sh

bash
#!/bin/bash
# PostgreSQL 连接数监控脚本

PG_HOST="localhost"
PG_PORT="5432"
PG_USER="postgres"
PG_DB="postgres"

# 最大连接数阈值
WARNING_THRESHOLD=80
CRITICAL_THRESHOLD=95

# 获取当前连接数和最大连接数
CURRENT_CONNECTIONS=$(psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -t -c "SELECT COUNT(*) FROM pg_stat_activity;")
MAX_CONNECTIONS=$(psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -t -c "SHOW max_connections;")

# 计算连接使用率
CONNECTION_USAGE=$(echo "scale=2; $CURRENT_CONNECTIONS * 100 / $MAX_CONNECTIONS" | bc)

# 发送告警
if (( $(echo "$CONNECTION_USAGE > $CRITICAL_THRESHOLD" | bc -l) )); then
    echo "CRITICAL: PostgreSQL 连接使用率过高 - $CONNECTION_USAGE%"
    # 发送紧急告警(如短信、钉钉)
    ./send_dingtalk.sh "PostgreSQL 连接使用率告警" "数据库连接使用率达到 ${CONNECTION_USAGE}%,已超过临界阈值 ${CRITICAL_THRESHOLD}%"
    exit 2
elif (( $(echo "$CONNECTION_USAGE > $WARNING_THRESHOLD" | bc -l) )); then
    echo "WARNING: PostgreSQL 连接使用率过高 - $CONNECTION_USAGE%"
    # 发送警告告警(如邮件)
    ./send_email.sh "PostgreSQL 连接使用率告警" "数据库连接使用率达到 ${CONNECTION_USAGE}%,已超过警告阈值 ${WARNING_THRESHOLD}%" "admin@example.com"
    exit 1
else
    echo "OK: PostgreSQL 连接使用率正常 - $CONNECTION_USAGE%"
    exit 0
fi

连接数优化配置

1. 调整最大连接数

sql
-- 查看当前配置
SHOW max_connections;

-- 修改最大连接数(需要重启 PostgreSQL 生效)
ALTER SYSTEM SET max_connections = '1000';

-- 修改超级用户预留连接数
ALTER SYSTEM SET superuser_reserved_connections = '10';

2. 配置连接池

使用连接池(如 PgBouncer、Pgpool-II)可以有效管理连接数:

ini
# PgBouncer 配置示例(pgbouncer.ini)
[databases]
* = host=localhost port=5432

[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 2000
default_pool_size = 20
min_pool_size = 5
reserve_pool_size = 10
reserve_pool_timeout = 5.0

3. 配置连接超时

sql
-- 设置 TCP 保持连接参数
ALTER SYSTEM SET tcp_keepalives_idle = '60';
ALTER SYSTEM SET tcp_keepalives_interval = '10';
ALTER SYSTEM SET tcp_keepalives_count = '6';

-- 设置连接空闲超时(需要连接池支持)
-- 对于 PgBouncer,可以在配置文件中设置
-- server_idle_timeout = 3600

连接数告警最佳实践

1. 合理设置告警阈值

  • 警告阈值:建议设置为最大连接数的 80%,给运维人员足够的响应时间
  • 临界阈值:建议设置为最大连接数的 95%,触发紧急告警
  • 空闲连接阈值:根据业务场景设置,一般建议 50-100 个

2. 告警发送策略

  • 警告级别:连接使用率超过 80% 时,发送邮件告警
  • 临界级别:连接使用率超过 95% 时,发送多渠道告警(邮件、短信、钉钉)
  • 告警频率:警告级别每 30 分钟发送一次,临界级别每 5 分钟发送一次

3. 连接数优化建议

  • 使用连接池:所有应用都应通过连接池访问数据库
  • 限制单应用连接数:为每个应用设置最大连接数限制
  • 及时释放空闲连接:配置合理的连接超时时间
  • 监控连接泄漏:定期检查长时间空闲的连接
  • 优化应用代码:减少连接占用时间,避免长事务

4. 定期审查连接数配置

  • 每季度审查一次最大连接数配置
  • 根据业务增长趋势调整连接数限制
  • 定期分析连接数使用模式,优化连接池配置

常见问题(FAQ)

Q1:如何查看 PostgreSQL 当前连接数?

A1:可以使用以下命令查看当前连接数:

sql
-- 查看总连接数
SELECT COUNT(*) FROM pg_stat_activity;

-- 查看详细的连接分布
SELECT 
    datname, 
    usename, 
    application_name, 
    state, 
    count(*) AS connection_count
FROM 
    pg_stat_activity
GROUP BY 
    datname, usename, application_name, state;

Q2:如何设置合理的最大连接数?

A2:设置最大连接数需要考虑:

  • 服务器硬件资源(CPU、内存)
  • 每个连接的内存占用(shared_buffers、work_mem 等)
  • 业务并发需求
  • 连接池配置

计算公式参考:

max_connections = (系统可用内存 - 操作系统和其他服务占用内存) / 每个连接所需内存

Q3:如何处理连接数达到上限的情况?

A3:处理连接数达到上限的方法:

  1. 检查是否有连接泄漏,终止长时间空闲的连接
  2. 临时增加最大连接数(如果服务器资源允许)
  3. 优化应用代码,减少连接占用时间
  4. 调整连接池配置,降低连接数
  5. 考虑水平扩展,增加数据库实例

Q4:如何自动终止空闲连接?

A4:可以使用以下方法自动终止空闲连接:

  1. 使用 pg_stat_activate 扩展自动终止空闲连接
  2. 创建定时任务,定期执行终止空闲连接的 SQL:
sql
-- 终止空闲超过10分钟的连接
SELECT pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE state = 'idle' 
  AND state_change < NOW() - INTERVAL '10 minutes';
  1. 在连接池中配置空闲连接超时

Q5:如何监控连接池的性能?

A5:监控连接池性能的方法:

  • 监控连接池的连接使用率、等待队列长度
  • 监控连接获取时间和连接创建时间
  • 监控连接池的错误日志,如连接拒绝、连接超时
  • 使用连接池提供的监控指标(如 PgBouncer 的 stats 管理接口)

Q6:如何预防连接数告警?

A6:预防连接数告警的方法:

  • 合理规划数据库架构,避免单点压力
  • 使用连接池管理连接
  • 定期监控连接数使用情况
  • 根据业务增长提前调整连接数配置
  • 优化应用代码,减少连接占用
  • 实施连接数限流策略