外观
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 -l2. 数据库连接状态验证
使用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模板
- 在Zabbix Web界面中,导入PostgreSQL模板(Template DB PostgreSQL)
- 配置PostgreSQL监控项,包括:
- 连接数监控
- 查询性能监控
- 复制状态监控
- 资源使用监控
- 配置告警规则,包括:
- 连接数超过阈值
- 慢查询数量超过阈值
- 复制延迟超过阈值
- 磁盘空间不足
最佳实践
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:可以使用以下方法自动化:
- 编写Shell脚本或Python脚本
- 使用crontab定时执行
- 配置Prometheus + Grafana监控
- 使用Zabbix等监控工具
- 集成到CI/CD流水线中
Q9:如何配置PostgreSQL状态告警?
A9:可以使用以下方法配置:
- 在Prometheus中配置Alertmanager
- 在Grafana中配置告警规则
- 使用Zabbix配置告警
- 使用Nagios配置告警
- 编写脚本发送邮件或短信告警
Q10:如何处理PostgreSQL服务无法启动的情况?
A10:处理步骤:
- 查看PostgreSQL日志,定位错误原因
- 检查数据目录权限是否正确
- 检查配置文件语法是否正确
- 检查端口是否被占用
- 检查磁盘空间是否充足
- 尝试使用pg_ctl start手动启动,查看详细错误信息
- 如果是数据损坏,考虑使用pg_resetwal修复
- 如果无法修复,使用备份恢复数据库
