Skip to content

PostgreSQL 服务状态验证

核心概念

服务状态验证是数据库运维的基础工作,用于确认PostgreSQL服务是否正常运行,以及系统资源使用情况。PostgreSQL服务状态验证主要涉及以下核心概念:

  • 服务运行状态:PostgreSQL进程是否正常运行
  • 连接状态:当前数据库连接数量和状态
  • 系统资源:CPU、内存、磁盘等资源使用情况
  • 数据库状态:数据库实例、表空间、锁等状态
  • 复制状态:主从复制的状态和延迟
  • 查询状态:当前正在执行的查询和性能

服务状态验证方法

1. 系统服务状态检查

使用systemctl命令(Systemd)

bash
# 检查PostgreSQL服务状态
sudo systemctl status postgresql-15

# 查看PostgreSQL服务是否启动
sudo systemctl is-active postgresql-15

# 查看PostgreSQL服务是否开机自启
sudo systemctl is-enabled postgresql-15

# 查看PostgreSQL服务日志
sudo journalctl -u postgresql-15 -n 50

使用pg_ctl命令

bash
# 检查PostgreSQL服务状态
pg_ctl status -D /var/lib/postgresql/15/main

# 查看PostgreSQL服务版本
pg_ctl --version

使用ps命令

bash
# 检查PostgreSQL进程是否运行
ps aux | grep postgres

# 查看PostgreSQL进程树
pstree -p $(pgrep -f postmaster)

# 统计PostgreSQL进程数量
ps aux | grep postgres | wc -l

2. 数据库连接状态验证

使用psql命令连接测试

bash
# 本地连接测试
psql -U postgres -d postgres -c "SELECT version();"

# 远程连接测试
psql -h 192.168.1.100 -p 5432 -U postgres -d postgres -c "SELECT 1;"

# 连接超时测试
time psql -h 192.168.1.101 -p 5432 -U postgres -d postgres -c "SELECT 1;" 2>&1

查看连接状态

sql
-- 查看当前所有连接
SELECT * FROM pg_stat_activity;

-- 查看活跃连接数量
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';

-- 查看空闲连接数量
SELECT count(*) FROM pg_stat_activity WHERE state = 'idle';

-- 查看长时间空闲的连接
SELECT 
    pid,
    datname,
    usename,
    application_name,
    client_addr,
    state,
    query_start,
    now() - query_start AS idle_time
FROM pg_stat_activity 
WHERE state = 'idle' 
    AND now() - query_start > interval '5 minutes' 
ORDER BY idle_time DESC;

3. 系统资源状态验证

查看系统资源使用情况

bash
# 查看CPU使用情况
top -p $(pgrep -f postmaster)

# 查看内存使用情况
free -h

# 查看磁盘使用情况
df -h

# 查看PostgreSQL数据目录磁盘使用情况
du -sh /var/lib/postgresql/15/main

# 查看WAL目录磁盘使用情况
du -sh /var/lib/postgresql/15/main/pg_wal

查看PostgreSQL资源使用情况

sql
-- 查看数据库大小
SELECT 
    datname,
    pg_size_pretty(pg_database_size(datname)) AS database_size
FROM pg_database 
ORDER BY pg_database_size(datname) DESC;

-- 查看表大小
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size
FROM pg_tables 
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC 
LIMIT 10;

-- 查看索引大小
SELECT 
    schemaname,
    tablename,
    indexname,
    pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename)) AS index_size
FROM pg_indexes 
ORDER BY pg_indexes_size(schemaname || '.' || tablename) DESC 
LIMIT 10;

4. 复制状态验证

sql
-- 查看主从复制状态(主节点)
SELECT * FROM pg_stat_replication;

-- 查看复制延迟(主节点)
SELECT 
    application_name,
    client_addr,
    state,
    sync_state,
    pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS send_lag,
    pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn) AS write_lag,
    pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn) AS flush_lag,
    pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag
FROM pg_stat_replication;

-- 查看从节点状态(从节点)
SELECT * FROM pg_stat_wal_receiver;

-- 查看从节点延迟(从节点)
SELECT 
    pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn()) AS replay_lag_bytes,
    pg_last_wal_receive_lsn(),
    pg_last_wal_replay_lsn(),
    pg_last_xact_replay_timestamp();

5. 查询性能状态验证

sql
-- 查看当前正在执行的查询
SELECT 
    pid,
    datname,
    usename,
    application_name,
    client_addr,
    state,
    query_start,
    now() - query_start AS query_time,
    query
FROM pg_stat_activity 
WHERE state = 'active' 
ORDER BY query_time DESC;

-- 查看慢查询
SELECT 
    pid,
    datname,
    usename,
    query_start,
    now() - query_start AS duration,
    query
FROM pg_stat_activity 
WHERE now() - query_start > interval '1 second' 
    AND state = 'active' 
ORDER BY duration DESC;

-- 查看锁信息
SELECT 
    locktype,
    database,
    relation::regclass,
    page,
    tuple,
    virtualxid,
    transactionid,
    classid,
    objid,
    objsubid,
    pid,
    mode,
    granted
FROM pg_locks 
WHERE pid IS NOT NULL;

自动化状态验证脚本

1. 简单状态检查脚本

bash
#!/bin/bash

# PostgreSQL服务状态检查脚本

# 配置参数
PG_VERSION="15"
PG_DATA_DIR="/var/lib/postgresql/${PG_VERSION}/main"
PG_USER="postgres"

# 检查服务状态
echo "=== PostgreSQL服务状态检查 ==="
systemctl status postgresql-${PG_VERSION} --no-pager

# 检查连接状态
echo -e "\n=== PostgreSQL连接状态检查 ==="
psql -U ${PG_USER} -d postgres -c "SELECT count(*) AS total_connections, state, count(*) FILTER (WHERE state = 'active') AS active_connections FROM pg_stat_activity GROUP BY state;"

# 检查系统资源
echo -e "\n=== 系统资源检查 ==="
echo "CPU使用率:"
top -bn1 | grep "Cpu(s)"
echo "内存使用率:"
free -h
echo "磁盘使用率:"
df -h

echo -e "\n=== PostgreSQL数据目录磁盘使用情况 ==="
du -sh ${PG_DATA_DIR}

# 检查复制状态
echo -e "\n=== 复制状态检查 ==="
psql -U ${PG_USER} -d postgres -c "SELECT application_name, client_addr, state, sync_state FROM pg_stat_replication;"

2. 完整状态监控脚本

bash
#!/bin/bash

# 完整的PostgreSQL状态监控脚本

# 配置参数
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="postgres"
PG_DATABASE="postgres"
OUTPUT_FILE="/tmp/postgres_status_$(date +%Y%m%d_%H%M%S).txt"

# 连接测试
connect_test() {
    echo "=== 连接测试 ===" >> ${OUTPUT_FILE}
    if psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "SELECT 1;" > /dev/null 2>&1; then
        echo "✓ 数据库连接正常" >> ${OUTPUT_FILE}
    else
        echo "✗ 数据库连接失败" >> ${OUTPUT_FILE}
        exit 1
    fi
}

# 服务状态
service_status() {
    echo -e "\n=== 服务状态 ===" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "SELECT version();" >> ${OUTPUT_FILE}
    
    echo -e "\n=== 系统状态 ===" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "SELECT current_database(), current_user, now();" >> ${OUTPUT_FILE}
}

# 连接状态
connection_status() {
    echo -e "\n=== 连接状态 ===" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        count(*) AS total_connections, \
        count(*) FILTER (WHERE state = 'active') AS active_connections, \
        count(*) FILTER (WHERE state = 'idle') AS idle_connections \
    FROM pg_stat_activity;" >> ${OUTPUT_FILE}
    
    echo -e "\n=== 活跃连接详情 ===" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        pid, \
        datname, \
        usename, \
        application_name, \
        client_addr, \
        state, \
        query_start, \
        now() - query_start AS query_time \
    FROM pg_stat_activity \
    WHERE state = 'active' \
    ORDER BY query_time DESC;" >> ${OUTPUT_FILE}
}

# 资源使用
resource_usage() {
    echo -e "\n=== 资源使用 ===" >> ${OUTPUT_FILE}
    
    echo -e "\n--- 数据库大小 ---" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        datname, \
        pg_size_pretty(pg_database_size(datname)) AS database_size \
    FROM pg_database \
    ORDER BY pg_database_size(datname) DESC;" >> ${OUTPUT_FILE}
    
    echo -e "\n--- 表大小前10 ---" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        schemaname, \
        tablename, \
        pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size \
    FROM pg_tables \
    ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC \
    LIMIT 10;" >> ${OUTPUT_FILE}
}

# 复制状态
replication_status() {
    echo -e "\n=== 复制状态 ===" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        application_name, \
        client_addr, \
        state, \
        sync_state, \
        pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag_bytes \
    FROM pg_stat_replication;" >> ${OUTPUT_FILE}
}

# 查询性能
query_performance() {
    echo -e "\n=== 查询性能 ===" >> ${OUTPUT_FILE}
    
    echo -e "\n--- 慢查询 ---" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        pid, \
        datname, \
        usename, \
        query_start, \
        now() - query_start AS duration, \
        substr(query, 1, 100) AS query \
    FROM pg_stat_activity \
    WHERE now() - query_start > interval '1 second' \
        AND state = 'active' \
    ORDER BY duration DESC;" >> ${OUTPUT_FILE}
    
    echo -e "\n--- 锁信息 ---" >> ${OUTPUT_FILE}
    psql -h ${PG_HOST} -p ${PG_PORT} -U ${PG_USER} -d ${PG_DATABASE} -c "\
    SELECT \
        locktype, \
        relation::regclass, \
        mode, \
        granted, \
        count(*) \
    FROM pg_locks \
    WHERE pid IS NOT NULL \
    GROUP BY locktype, relation, mode, granted;" >> ${OUTPUT_FILE}
}

# 执行检查
connect_test
service_status
connection_status
resource_usage
replication_status
query_performance

echo -e "\n=== 检查完成 ===" >> ${OUTPUT_FILE}
echo "状态报告已生成:${OUTPUT_FILE}"
cat ${OUTPUT_FILE}

监控与告警

1. 使用Prometheus + Grafana监控

安装PostgreSQL Exporter

bash
# 下载PostgreSQL Exporter
wget https://github.com/prometheus-community/postgres_exporter/releases/download/v0.14.0/postgres_exporter-v0.14.0.linux-amd64.tar.gz

tar xvfz postgres_exporter-v0.14.0.linux-amd64.tar.gz
cd postgres_exporter-v0.14.0.linux-amd64

# 配置PostgreSQL连接
cat > .env << EOF
DATA_SOURCE_NAME=postgresql://postgres:password@localhost:5432/postgres?sslmode=disable
EOF

# 启动PostgreSQL Exporter
./postgres_exporter --web.listen-address=:9187

配置Prometheus

yaml
# prometheus.yml配置
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'postgres'
    static_configs:
      - targets: ['localhost:9187']

2. 使用Zabbix监控

安装Zabbix PostgreSQL模板

  1. 在Zabbix Web界面中,导入PostgreSQL模板(Template DB PostgreSQL)
  2. 配置PostgreSQL监控项,包括:
    • 连接数监控
    • 查询性能监控
    • 复制状态监控
    • 资源使用监控
  3. 配置告警规则,包括:
    • 连接数超过阈值
    • 慢查询数量超过阈值
    • 复制延迟超过阈值
    • 磁盘空间不足

最佳实践

1. 定期检查最佳实践

  • 制定检查计划:根据业务重要性,制定每日、每周、每月的检查计划
  • 自动化检查:使用脚本自动化执行状态检查,减少人工干预
  • 建立基线:记录正常状态下的各项指标,建立性能基线
  • 配置告警:设置合理的告警阈值,及时发现异常情况
  • 记录日志:保存检查结果,便于问题追溯和趋势分析

2. 状态验证频率建议

  • 服务状态:每1-5分钟检查一次
  • 连接状态:每5-15分钟检查一次
  • 资源使用:每15-30分钟检查一次
  • 复制状态:每1-5分钟检查一次
  • 查询性能:每5-15分钟检查一次
  • 完整状态报告:每天生成一次

3. 异常处理最佳实践

  • 建立响应流程:制定明确的异常响应流程和责任人
  • 快速定位问题:使用多种检查方法,快速定位问题根源
  • 优先恢复服务:在保证数据安全的前提下,优先恢复服务
  • 分析根本原因:问题解决后,分析根本原因,防止再次发生
  • 更新监控规则:根据新发现的问题,更新监控规则和告警阈值

常见问题(FAQ)

Q1:如何快速检查PostgreSQL服务是否正常运行?

A1:可以使用以下命令快速检查:

bash
# 使用systemctl检查服务状态
sudo systemctl status postgresql-15

# 使用psql测试连接
psql -U postgres -d postgres -c "SELECT 1;"

Q2:如何查看PostgreSQL的版本信息?

A2:可以使用以下命令查看:

bash
# 使用psql查看版本
psql -V

# 连接到数据库查看详细版本
psql -U postgres -d postgres -c "SELECT version();"

Q3:如何查看PostgreSQL的连接数?

A3:可以使用以下命令查看:

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

-- 按状态分组查看连接数
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;

Q4:如何查看PostgreSQL的慢查询?

A4:可以使用以下命令查看:

sql
SELECT 
    pid,
    datname,
    usename,
    query_start,
    now() - query_start AS duration,
    query
FROM pg_stat_activity 
WHERE now() - query_start > interval '1 second' 
    AND state = 'active' 
ORDER BY duration DESC;

Q5:如何查看PostgreSQL的复制状态?

A5:可以使用以下命令查看:

sql
-- 在主节点上查看
SELECT application_name, client_addr, state, sync_state FROM pg_stat_replication;

-- 在从节点上查看
SELECT * FROM pg_stat_wal_receiver;

Q6:如何查看PostgreSQL的数据目录大小?

A6:可以使用以下命令查看:

bash
# 使用du命令查看
du -sh /var/lib/postgresql/15/main

# 使用SQL查询数据库大小
psql -U postgres -d postgres -c "SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database;"

Q7:如何检查PostgreSQL的锁情况?

A7:可以使用以下命令查看:

sql
SELECT 
    locktype,
    relation::regclass,
    mode,
    granted,
    count(*) 
FROM pg_locks 
WHERE pid IS NOT NULL 
GROUP BY locktype, relation, mode, granted;

Q8:如何自动化PostgreSQL状态检查?

A8:可以使用以下方法自动化:

  1. 编写Shell脚本或Python脚本
  2. 使用crontab定时执行
  3. 配置Prometheus + Grafana监控
  4. 使用Zabbix等监控工具
  5. 集成到CI/CD流水线中

Q9:如何配置PostgreSQL状态告警?

A9:可以使用以下方法配置:

  1. 在Prometheus中配置Alertmanager
  2. 在Grafana中配置告警规则
  3. 使用Zabbix配置告警
  4. 使用Nagios配置告警
  5. 编写脚本发送邮件或短信告警

Q10:如何处理PostgreSQL服务无法启动的情况?

A10:处理步骤:

  1. 查看PostgreSQL日志,定位错误原因
  2. 检查数据目录权限是否正确
  3. 检查配置文件语法是否正确
  4. 检查端口是否被占用
  5. 检查磁盘空间是否充足
  6. 尝试使用pg_ctl start手动启动,查看详细错误信息
  7. 如果是数据损坏,考虑使用pg_resetwal修复
  8. 如果无法修复,使用备份恢复数据库