一、PostgreSQL概述
1. 什么是PostgreSQL
PostgreSQL 是一个功能强大的开源对象关系型数据库管理系统,以其可靠性、功能健壮性和性能著称。
text
PostgreSQL特点:
├── 开源免费(BSD许可证)
├── ACID兼容(事务支持)
├── 支持复杂查询
├── 支持JSON/JSONB
├── 支持全文搜索
├── 支持地理空间数据
├── 多种复制选项
└── 扩展性极强
2. 版本信息
sql
-- 查看PostgreSQL版本
SELECT version();
-- 查看服务器状态
SHOW server_version;
SHOW server_encoding;
SHOW data_directory;
二、PostgreSQL日常维护
1. 服务管理命令
bash
# CentOS/RHEL 7+
systemctl start postgresql # 启动服务
systemctl stop postgresql # 停止服务
systemctl restart postgresql # 重启服务
systemctl reload postgresql # 重载配置
systemctl status postgresql # 查看状态
systemctl enable postgresql # 开机自启
systemctl disable postgresql # 取消自启
# Ubuntu/Debian
systemctl start postgresql
systemctl stop postgresql
systemctl restart postgresql
# 通用方式
pg_ctl start -D /var/lib/pgsql/data
pg_ctl stop -D /var/lib/pgsql/data
pg_ctl restart -D /var/lib/pgsql/data
pg_ctl status -D /var/lib/pgsql/data
2. 数据库连接管理
bash
# 使用psql连接
psql -h localhost -p 5432 -U postgres -d postgres
# 连接参数说明
# -h: 主机地址
# -p: 端口(默认5432)
# -U: 用户名
# -d: 数据库名
# -W: 提示输入密码
# 执行SQL文件
psql -U postgres -d mydb -f /path/to/script.sql
# 执行单条SQL
psql -U postgres -d mydb -c "SELECT * FROM users;"
# 输出查询结果到文件
psql -U postgres -d mydb -c "SELECT * FROM users" -o output.txt
# 使用连接字符串
psql "postgresql://postgres:password@localhost:5432/mydb"
3. 用户和权限管理
sql
-- 创建用户
CREATE USER appuser WITH PASSWORD 'strong_password';
CREATE ROLE readonly WITH LOGIN PASSWORD 'readonly_pass';
-- 创建超级用户
CREATE USER admin WITH SUPERUSER PASSWORD 'admin_pass';
-- 修改密码
ALTER USER appuser WITH PASSWORD 'new_password';
-- 删除用户
DROP USER appuser;
-- 查看所有用户
\du
SELECT usename FROM pg_user;
-- 授予权限
GRANT CONNECT ON DATABASE mydb TO appuser;
GRANT USAGE ON SCHEMA public TO appuser;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser;
GRANT ALL PRIVILEGES ON DATABASE mydb TO appuser;
-- 撤销权限
REVOKE INSERT ON users FROM appuser;
-- 授予未来表的权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
-- 创建角色组
CREATE ROLE developers;
GRANT developers TO alice, bob;
4. 数据库管理
sql
-- 创建数据库
CREATE DATABASE mydb;
CREATE DATABASE mydb OWNER appuser;
CREATE DATABASE mydb ENCODING 'UTF8' LC_COLLATE 'zh_CN.UTF-8';
-- 查看数据库列表
\l
SELECT datname FROM pg_database;
-- 切换数据库
\c mydb
CONNECT TO mydb;
-- 删除数据库
DROP DATABASE mydb;
-- 强制删除(先断开连接)
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'mydb';
DROP DATABASE mydb;
-- 查看数据库大小
SELECT pg_database_size('mydb');
SELECT pg_size_pretty(pg_database_size('mydb'));
-- 查看所有数据库大小
SELECT datname, pg_size_pretty(pg_database_size(datname))
FROM pg_database ORDER BY pg_database_size(datname) DESC;
5. 表空间管理
sql
-- 创建表空间
CREATE TABLESPACE fastspace LOCATION '/data/postgresql/fastspace';
CREATE TABLESPACE archive LOCATION '/data/postgresql/archive';
-- 创建表在指定表空间
CREATE TABLE users (id INT, name TEXT) TABLESPACE fastspace;
-- 移动表到其他表空间
ALTER TABLE users SET TABLESPACE archive;
-- 查看表空间
\db
SELECT * FROM pg_tablespace;
-- 设置默认表空间
SET default_tablespace = fastspace;
-- 删除表空间(需为空)
DROP TABLESPACE archive;
6. 表维护
sql
-- 查看所有表
\d
\dt
SELECT tablename FROM pg_tables WHERE schemaname='public';
-- 查看表结构
\d users
\d+ users
-- 查看表大小
SELECT pg_size_pretty(pg_relation_size('users'));
SELECT pg_size_pretty(pg_total_relation_size('users'));
-- 查看所有表大小
SELECT
tablename,
pg_size_pretty(pg_total_relation_size(tablename)) AS size
FROM pg_tables
WHERE schemaname='public'
ORDER BY pg_total_relation_size(tablename) DESC;
-- 分析表(更新统计信息)
ANALYZE users;
ANALYZE VERBOSE users;
-- 分析所有表
ANALYZE;
-- 清理并分析
VACUUM users;
VACUUM ANALYZE users;
-- 完全清理(回收空间)
VACUUM FULL users;
-- 重新索引
REINDEX INDEX idx_users_name;
REINDEX TABLE users;
REINDEX DATABASE mydb;
-- 检查表
-- PostgreSQL没有直接的表检查命令,可以使用pg_checksums
7. 索引维护
sql
-- 查看索引
\di
SELECT * FROM pg_indexes WHERE tablename='users';
-- 创建索引
CREATE INDEX idx_users_name ON users(name);
CREATE UNIQUE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_name_lower ON users(LOWER(name));
CREATE INDEX idx_users_name_gist ON users USING GIST(name);
CREATE INDEX idx_users_data_gin ON users USING GIN(data);
-- 部分索引
CREATE INDEX idx_active_users ON users(id) WHERE active = true;
-- 表达式索引
CREATE INDEX idx_users_age_group ON users((age/10));
-- 并发创建索引(不锁表)
CREATE INDEX CONCURRENTLY idx_users_name ON users(name);
-- 删除索引
DROP INDEX idx_users_name;
DROP INDEX CONCURRENTLY idx_users_name;
-- 重建索引
REINDEX INDEX idx_users_name;
REINDEX TABLE users CONCURRENTLY;
-- 查看索引使用情况
SELECT
schemaname,
tablename,
indexname,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0;
8. 日志管理
bash
# 日志配置文件位置
/etc/postgresql/14/main/postgresql.conf # Ubuntu
/var/lib/pgsql/14/data/postgresql.conf # CentOS
# 日志相关配置
log_directory = 'pg_log' # 日志目录
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d # 日志轮转周期
log_rotation_size = 10MB # 日志文件大小
log_truncate_on_rotation = on
# 日志内容设置
log_statement = 'all' # 记录所有语句
log_statement = 'ddl' # 只记录DDL
log_statement = 'mod' # 记录DML
log_min_duration_statement = 1000 # 记录慢查询(毫秒)
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
# 查看日志
tail -f /var/log/postgresql/postgresql-14-main.log
# 日志分析查询
SELECT
log_time,
user_name,
database_name,
message
FROM pg_read_log('postgresql.log')
WHERE message LIKE '%ERROR%'
ORDER BY log_time DESC
LIMIT 10;
9. 备份与恢复
bash
# 1. pg_dump - 逻辑备份(单数据库)
pg_dump -U postgres mydb > mydb.sql
pg_dump -U postgres -Fc mydb > mydb.dump # 自定义格式(压缩)
pg_dump -U postgres -Ft mydb > mydb.tar # tar格式
pg_dump -U postgres -Fd mydb -f mydb_dir # 目录格式
# 2. pg_dumpall - 备份所有数据库
pg_dumpall -U postgres > all.sql
pg_dumpall -U postgres --globals-only > globals.sql # 只备份全局对象
# 3. 选择性备份
pg_dump -U postgres -t users -t orders mydb > selected.sql # 只备份特定表
pg_dump -U postgres --schema-only mydb > schema.sql # 只备份结构
pg_dump -U postgres --data-only mydb > data.sql # 只备份数据
pg_dump -U postgres --exclude-table=logs mydb > no_logs.sql # 排除表
# 4. 恢复
psql -U postgres -d mydb < mydb.sql
pg_restore -U postgres -d mydb mydb.dump
pg_restore -U postgres -d mydb -t users mydb.dump # 只恢复特定表
# 5. 并行备份
pg_dump -U postgres -j 4 -Fd mydb -f mydb_dir
# 6. 压缩备份
pg_dump -U postgres mydb | gzip > mydb.sql.gz
gunzip -c mydb.sql.gz | psql -U postgres -d mydb
# 7. 远程备份
pg_dump -h remote_host -U postgres mydb > remote_backup.sql
10. 备份脚本示例
bash
#!/bin/bash
# postgres_backup.sh - PostgreSQL自动备份脚本
# 配置
BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="postgres"
DB_PASS="password"
DB_HOST="localhost"
DB_PORT="5432"
RETENTION_DAYS=7
# 导出密码(避免交互)
export PGPASSWORD=$DB_PASS
# 创建备份目录
mkdir -p $BACKUP_DIR/{daily,weekly,monthly,logs}
# 备份单个数据库
backup_database() {
local db=$1
local type=$2
local backup_file="$BACKUP_DIR/$type/${db}_${DATE}.sql.gz"
echo "备份数据库: $db"
pg_dump -h $DB_HOST -p $DB_PORT -U $DB_USER -d $db | gzip > $backup_file
if [ $? -eq 0 ]; then
echo "✓ $db 备份成功: $backup_file"
echo "$DATE|$db|成功|$backup_file" >> $BACKUP_DIR/logs/backup.log
else
echo "✗ $db 备份失败"
echo "$DATE|$db|失败|" >> $BACKUP_DIR/logs/backup.log
fi
}
# 备份所有数据库
backup_all() {
local backup_file="$BACKUP_DIR/daily/all_${DATE}.sql.gz"
echo "备份所有数据库..."
pg_dumpall -h $DB_HOST -p $DB_PORT -U $DB_USER | gzip > $backup_file
echo "✓ 所有数据库备份完成"
}
# 备份全局对象
backup_globals() {
local backup_file="$BACKUP_DIR/daily/globals_${DATE}.sql"
echo "备份全局对象..."
pg_dumpall -h $DB_HOST -p $DB_PORT -U $DB_USER --globals-only > $backup_file
}
# 清理旧备份
cleanup_old() {
echo "清理 $RETENTION_DAYS 天前的备份..."
find $BACKUP_DIR/daily -type f -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR/logs -type f -mtime +30 -delete
}
# 每周完整备份
weekly_backup() {
if [ $(date +%u) -eq 7 ]; then
cp $BACKUP_DIR/daily/all_${DATE}.sql.gz $BACKUP_DIR/weekly/
fi
}
# 每月备份
monthly_backup() {
if [ $(date +%d) -eq 1 ]; then
cp $BACKUP_DIR/daily/all_${DATE}.sql.gz $BACKUP_DIR/monthly/
fi
}
# 主函数
main() {
echo "开始备份 - $(date)"
echo "===================="
# 获取数据库列表
databases=$(psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" | tr -d ' ')
# 备份每个数据库
for db in $databases; do
if [ "$db" != "postgres" ]; then
backup_database $db "daily"
fi
done
# 备份postgres数据库
backup_database "postgres" "daily"
# 备份所有数据库
backup_all
# 备份全局对象
backup_globals
# 清理旧备份
cleanup_old
# 每周/月备份
weekly_backup
monthly_backup
echo "===================="
echo "备份完成 - $(date)"
}
main
三、PostgreSQL常用命令
1. psql元命令(快捷命令)
sql
-- 连接和退出
\c mydb -- 切换到mydb数据库
\c mydb postgres -- 以postgres用户连接mydb
\q -- 退出psql
\! -- 执行shell命令
\? -- 查看所有元命令
-- 数据库对象查看
\l -- 列出所有数据库
\l+ -- 列出数据库详细信息
\dn -- 列出所有schema
\dt -- 列出所有表
\dt+ -- 列出表详细信息
\di -- 列出所有索引
\dv -- 列出所有视图
\ds -- 列出所有序列
\df -- 列出所有函数
\du -- 列出所有用户
\dg -- 列出所有角色
-- 表结构查看
\d users -- 查看表结构
\d+ users -- 详细表结构
\d users.* -- 查看所有users开头的表
\dt public.* -- 查看public schema下的所有表
-- 权限查看
\dp users -- 查看表权限
\z users -- 同上
\drds -- 查看角色权限
-- 索引查看
\di users* -- 查看users表的索引
-- 查看SQL执行历史
\s -- 查看历史
\s filename -- 保存历史到文件
-- 输出控制
\a -- 切换对齐模式
\H -- HTML输出格式
\t -- 只显示记录
\x -- 扩展显示(每字段一行)
\o filename -- 输出到文件
\o -- 恢复输出到屏幕
-- 执行计时
\timing on -- 开启执行计时
\timing off -- 关闭执行计时
-- 查看运行信息
\watch 2 -- 每2秒重复执行上一条SQL
\g -- 执行上一条SQL
\g filename -- 执行并输出到文件
2. 信息查询命令
sql
-- 查看当前连接信息
SELECT current_database();
SELECT current_user;
SELECT current_schema();
SELECT inet_client_addr();
SELECT inet_server_addr();
SELECT version();
-- 查看配置参数
SHOW all;
SHOW data_directory;
SHOW config_file;
SHOW max_connections;
SHOW shared_buffers;
-- 修改配置(会话级)
SET work_mem = '64MB';
SET timezone = 'Asia/Shanghai';
-- 查看运行时统计
SELECT * FROM pg_stat_activity; -- 当前活动连接
SELECT * FROM pg_stat_database; -- 数据库统计
SELECT * FROM pg_stat_user_tables; -- 用户表统计
SELECT * FROM pg_stat_user_indexes; -- 索引使用统计
SELECT * FROM pg_statio_user_tables; -- I/O统计
3. 性能监控命令
sql
-- 查看当前活动查询
SELECT
pid,
usename,
application_name,
client_addr,
state,
query,
query_start,
now() - query_start AS duration
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
-- 查看阻塞查询
SELECT
blocked_locks.pid AS blocked_pid,
blocked_activity.query AS blocked_query,
blocking_locks.pid AS blocking_pid,
blocking_activity.query AS blocking_query
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;
-- 终止查询
SELECT pg_cancel_backend(pid); -- 取消查询
SELECT pg_terminate_backend(pid); -- 终止连接
-- 查看表大小
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS total_size,
pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) AS table_size,
pg_size_pretty(pg_indexes_size(schemaname||'.'||tablename)) AS index_size
FROM pg_tables
WHERE schemaname NOT IN ('information_schema', 'pg_catalog')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 20;
-- 查看未使用索引
SELECT
schemaname,
tablename,
indexname,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY idx_tup_read DESC;
-- 查看慢查询(需要开启pg_stat_statements扩展)
CREATE EXTENSION pg_stat_statements;
SELECT
query,
calls,
total_time,
mean_time,
rows
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
4. 维护命令
sql
-- 清理命令
VACUUM; -- 清理所有数据库
VACUUM FULL; -- 完全清理(回收空间)
VACUUM ANALYZE; -- 清理并更新统计信息
VACUUM VERBOSE users; -- 详细输出清理信息
-- 分析命令
ANALYZE; -- 更新所有表统计信息
ANALYZE users; -- 更新指定表
ANALYZE VERBOSE users; -- 详细输出
-- 重建索引
REINDEX INDEX idx_users_name; -- 重建指定索引
REINDEX TABLE users; -- 重建表所有索引
REINDEX DATABASE mydb; -- 重建数据库所有索引
REINDEX SCHEMA public; -- 重建schema所有索引
REINDEX SYSTEM mydb; -- 重建系统索引
-- 集群表(按索引顺序重排)
CLUSTER users USING idx_users_name;
CLUSTER VERBOSE;
-- 冻结表(标记为不需要清理)
VACUUM FREEZE users;
5. 锁定查询
sql
-- 查看当前锁
SELECT
locktype,
database,
relation::regclass,
page,
tuple,
virtualxid,
transactionid,
mode,
granted,
pid
FROM pg_locks
WHERE NOT granted;
-- 查看锁等待关系
SELECT
w.pid AS waiting_pid,
w.query AS waiting_query,
l.pid AS locking_pid,
l.query AS locking_query
FROM pg_stat_activity w
JOIN pg_locks wl ON w.pid = wl.pid
JOIN pg_locks ll ON wl.locktype = ll.locktype
AND wl.database IS NOT DISTINCT FROM ll.database
AND wl.relation IS NOT DISTINCT FROM ll.relation
AND wl.page IS NOT DISTINCT FROM ll.page
AND wl.tuple IS NOT DISTINCT FROM ll.tuple
AND wl.virtualxid IS NOT DISTINCT FROM ll.virtualxid
AND wl.transactionid IS NOT DISTINCT FROM ll.transactionid
AND wl.classid IS NOT DISTINCT FROM ll.classid
AND wl.objid IS NOT DISTINCT FROM ll.objid
AND wl.objsubid IS NOT DISTINCT FROM ll.objsubid
AND wl.pid != ll.pid
JOIN pg_stat_activity l ON ll.pid = l.pid
WHERE NOT wl.granted;
四、日常巡检脚本
bash
#!/bin/bash
# postgres_checkup.sh - PostgreSQL日常巡检脚本
# 配置
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="postgres"
PG_DB="postgres"
PG_PASS="password"
export PGPASSWORD=$PG_PASS
# 颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "=========================================="
echo "PostgreSQL巡检报告 - $(date)"
echo "=========================================="
# 1. 数据库状态
echo -e "\n1. 数据库服务状态:"
pg_isready -h $PG_HOST -p $PG_PORT -U $PG_USER
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ PostgreSQL服务正常${NC}"
else
echo -e "${RED}✗ PostgreSQL服务异常${NC}"
fi
# 2. 连接数检查
echo -e "\n2. 连接数检查:"
MAX_CONN=$(psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -t -c "SHOW max_connections;" | tr -d ' ')
CURR_CONN=$(psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -t -c "SELECT COUNT(*) FROM pg_stat_activity;" | tr -d ' ')
echo "最大连接数: $MAX_CONN"
echo "当前连接数: $CURR_CONN"
USAGE=$(echo "scale=2; $CURR_CONN * 100 / $MAX_CONN" | bc)
echo "使用率: ${USAGE}%"
if (( $(echo "$USAGE > 80" | bc -l) )); then
echo -e "${RED}⚠ 连接数过高${NC}"
else
echo -e "${GREEN}✓ 连接数正常${NC}"
fi
# 3. 数据库大小
echo -e "\n3. 数据库大小:"
psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -c "
SELECT
datname,
pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
WHERE datistemplate = false
ORDER BY pg_database_size(datname) DESC;"
# 4. 表大小TOP10
echo -e "\n4. 最大的10个表:"
psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -c "
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS total_size
FROM pg_tables
WHERE schemaname NOT IN ('information_schema', 'pg_catalog')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;"
# 5. 未使用索引
echo -e "\n5. 未使用的索引:"
psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -c "
SELECT
schemaname,
tablename,
indexname,
idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY idx_tup_read DESC
LIMIT 10;"
# 6. 死锁检查
echo -e "\n6. 死锁检查:"
DEADLOCKS=$(psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -t -c "SELECT deadlocks FROM pg_stat_database WHERE datname='$PG_DB';" | tr -d ' ')
echo "死锁次数: $DEADLOCKS"
# 7. 慢查询检查
echo -e "\n7. 慢查询检查:"
psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -c "
SELECT
pid,
usename,
application_name,
state,
now() - query_start AS duration,
left(query, 100) AS query_preview
FROM pg_stat_activity
WHERE state != 'idle'
AND now() - query_start > interval '5 seconds'
ORDER BY duration DESC;"
# 8. 检查需要VACUUM的表
echo -e "\n8. 需要VACUUM的表:"
psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB -c "
SELECT
schemaname,
tablename,
n_dead_tup,
n_live_tup,
round(100 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) AS dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC;"
# 9. 备份检查
echo -e "\n9. 最新备份:"
find /backup/postgresql -name "*.sql.gz" -type f -mtime -1 2>/dev/null | head -5
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ 最近24小时内有备份${NC}"
else
echo -e "${RED}✗ 最近24小时内无备份${NC}"
fi
# 10. 磁盘空间
echo -e "\n10. 数据目录磁盘空间:"
df -h /var/lib/pgsql 2>/dev/null || df -h /var/lib/postgresql
echo -e "\n=========================================="
echo "巡检完成"
五、常见故障处理
1. 无法连接
bash
# 检查服务状态
systemctl status postgresql
# 检查端口监听
netstat -tlnp | grep 5432
# 检查pg_hba.conf配置
cat /var/lib/pgsql/data/pg_hba.conf
# 常见配置
# TYPE DATABASE USER ADDRESS METHOD
# host all all 0.0.0.0/0 md5
# 检查postgresql.conf
grep listen_addresses /var/lib/pgsql/data/postgresql.conf
# 修改后需要重启
systemctl restart postgresql
2. 清理死连接
sql
-- 查找死连接
SELECT pid, usename, query, state
FROM pg_stat_activity
WHERE state = 'idle' AND state_change < now() - interval '1 hour';
-- 终止死连接
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle' AND state_change < now() - interval '1 hour';
3. 恢复被删除的数据
bash
# 从备份恢复
pg_restore -U postgres -d mydb mydb.dump
# 从WAL日志恢复(需开启归档)
# 需要完整的时间点恢复配置
4. 清理膨胀的表
sql
-- 查看膨胀
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size,
n_dead_tup
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC;
-- 清理膨胀
VACUUM FULL VERBOSE users;
六、总结
日常维护任务清单
text
每日任务:
□ 检查服务状态
□ 检查连接数
□ 检查磁盘空间
□ 查看错误日志
□ 检查备份状态
每周任务:
□ 清理旧备份
□ 分析统计信息
□ 检查索引使用
□ 清理死连接
每月任务:
□ VACUUM FULL
□ REINDEX
□ 日志归档
□ 性能分析
□ 安全审计
常用命令速查
| 操作 | 命令 |
|---|---|
| 连接数据库 | psql -U user -d db |
| 查看所有数据库 | \l |
| 查看所有表 | \dt |
| 查看表结构 | \d table |
| 切换数据库 | \c db |
| 退出 | \q |
| 备份数据库 | pg_dump db > backup.sql |
| 恢复数据库 | psql db < backup.sql |
| 查看帮助 | \? |