PostgreSQL 安装和使用指南
目录
概述
PostgreSQL 是一个功能强大的开源关系型数据库管理系统,支持 SQL 标准,并提供了许多现代特性,如复杂查询、外键、触发器、视图、事务完整性等。
主要特性
- ACID 事务支持
- 多版本并发控制 (MVCC)
- 支持多种数据类型
- 可扩展的类型系统
- 丰富的索引类型
- 全文搜索
- JSON 和 JSONB 支持
- 存储过程和函数
安装 PostgreSQL
在 Ubuntu/Debian 上安装
# 更新包列表
sudo apt update
# 安装 PostgreSQL
sudo apt install postgresql postgresql-contrib
# 检查版本
psql --version在 CentOS/RHEL 上安装
# 安装 PostgreSQL 仓库
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 安装 PostgreSQL
sudo yum install -y postgresql15-server postgresql15-contrib
# 初始化数据库
sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
# 启动服务
sudo systemctl start postgresql-15
sudo systemctl enable postgresql-15在 macOS 上安装
# 使用 Homebrew 安装
brew install postgresql
# 启动服务
brew services start postgresql使用 Docker 安装
# 拉取 PostgreSQL 镜像
docker pull postgres:15
# 运行容器
docker run --name postgres-db -e POSTGRES_PASSWORD=mypassword -e POSTGRES_DB=mydb -p 5432:5432 -d postgres:15基本配置
配置文件位置
PostgreSQL 的主要配置文件通常位于:
/etc/postgresql/15/main/postgresql.conf(Ubuntu/Debian)/var/lib/pgsql/15/data/postgresql.conf(CentOS/RHEL)/usr/local/var/postgres/postgresql.conf(macOS with Homebrew)
常用配置参数
# 监听地址 (默认只监听本地)
listen_addresses = '*'
# 端口 (默认 5432)
port = 5432
# 最大连接数
max_connections = 100
# 共享缓冲区大小 (设置为系统内存的 25%)
shared_buffers = 256MB
# 工作内存
work_mem = 4MB
# 维护工作内存
maintenance_work_mem = 64MB
# 检查点间隔
checkpoint_completion_target = 0.9
# WAL 日志级别
wal_level = replica
# 最大 WAL 发送者进程数
max_wal_senders = 10修改配置后重启服务
# Ubuntu/Debian
sudo systemctl restart postgresql
# CentOS/RHEL
sudo systemctl restart postgresql-15
# macOS
brew services restart postgresql启动和停止服务
系统服务管理
# 启动服务
sudo systemctl start postgresql
# 停止服务
sudo systemctl stop postgresql
# 重启服务
sudo systemctl restart postgresql
# 查看状态
sudo systemctl status postgresql
# 开机自启
sudo systemctl enable postgresql手动启动
# 切换到 postgres 用户
sudo -u postgres -i
# 启动 PostgreSQL
pg_ctl -D /var/lib/postgresql/15/main start
# 停止 PostgreSQL
pg_ctl -D /var/lib/postgresql/15/main stop用户和权限管理
切换到 postgres 用户
sudo -u postgres psql
# 或者
sudo su - postgres
psql创建用户
-- 创建普通用户
CREATE USER username WITH PASSWORD 'password';
-- 创建超级用户
CREATE USER admin WITH SUPERUSER PASSWORD 'password';
-- 创建用户并指定权限
CREATE USER app_user WITH PASSWORD 'password'
CREATEDB
CREATEROLE;修改用户密码
-- 修改密码
ALTER USER username PASSWORD 'new_password';
-- 强制修改密码 (下次登录时)
ALTER USER username PASSWORD NULL;删除用户
DROP USER username;角色和权限
-- 创建角色
CREATE ROLE readonly;
-- 授予权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
-- 撤销权限
REVOKE SELECT ON ALL TABLES IN SCHEMA public FROM readonly;
-- 授予数据库连接权限
GRANT CONNECT ON DATABASE mydb TO username;
-- 授予表权限
GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO username;数据库操作
创建数据库
-- 创建数据库
CREATE DATABASE mydb;
-- 创建数据库并指定所有者
CREATE DATABASE mydb OWNER username;
-- 创建数据库并指定编码
CREATE DATABASE mydb
OWNER username
ENCODING 'UTF8'
LC_COLLATE 'en_US.UTF-8'
LC_CTYPE 'en_US.UTF-8'
TEMPLATE template0;连接数据库
# 使用 psql 连接
psql -h localhost -U username -d mydb
# 或者直接连接默认数据库
psql -U username mydb列出数据库
-- 列出所有数据库
\l
-- 或者
SELECT datname FROM pg_database;删除数据库
-- 删除数据库 (需要超级用户权限)
DROP DATABASE mydb;表和数据操作
创建表
-- 创建简单表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建带有外键的表
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
title VARCHAR(200) NOT NULL,
content TEXT,
published_at TIMESTAMP
);数据类型
| 数据类型 | 描述 | 示例 |
|---|---|---|
| SERIAL | 自增整数 | id SERIAL |
| INTEGER | 整数 | age INTEGER |
| VARCHAR(n) | 可变长度字符串 | name VARCHAR(100) |
| TEXT | 无限长度文本 | content TEXT |
| BOOLEAN | 布尔值 | active BOOLEAN |
| TIMESTAMP | 时间戳 | created_at TIMESTAMP |
| DATE | 日期 | birth_date DATE |
| NUMERIC(p,s) | 精确数值 | price NUMERIC(10,2) |
| JSONB | JSON 数据 | metadata JSONB |
插入数据
-- 插入单行数据
INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');
-- 插入多行数据
INSERT INTO users (name, email) VALUES
('李四', 'lisi@example.com'),
('王五', 'wangwu@example.com');
-- 插入并返回数据
INSERT INTO users (name, email) VALUES ('赵六', 'zhaoliu@example.com')
RETURNING id, name, email;查询数据
-- 查询所有数据
SELECT * FROM users;
-- 选择特定列
SELECT name, email FROM users;
-- 带条件查询
SELECT * FROM users WHERE name LIKE '张%';
-- 排序
SELECT * FROM users ORDER BY created_at DESC;
-- 分页
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;
-- 聚合查询
SELECT COUNT(*) FROM users;
SELECT AVG(age) FROM users WHERE age IS NOT NULL;
-- 连接查询
SELECT u.name, p.title
FROM users u
JOIN posts p ON u.id = p.user_id;更新数据
-- 更新单行
UPDATE users SET name = '张三新' WHERE id = 1;
-- 更新多行
UPDATE users SET active = true WHERE created_at < '2024-01-01';
-- 更新并返回
UPDATE users SET email = 'newemail@example.com' WHERE id = 1
RETURNING id, name, email;删除数据
-- 删除特定行
DELETE FROM users WHERE id = 1;
-- 删除所有数据
DELETE FROM users;
-- 清空表 (保留表结构)
TRUNCATE TABLE users;索引
-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_name ON users(name);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_users_unique_email ON users(email);
-- 创建复合索引
CREATE INDEX idx_posts_user_published ON posts(user_id, published_at);
-- 查看索引
SELECT * FROM pg_indexes WHERE tablename = 'users';
-- 删除索引
DROP INDEX idx_users_email;备份和恢复
使用 pg_dump 备份
# 备份整个数据库
pg_dump -U username -h localhost mydb > backup.sql
# 备份压缩格式
pg_dump -U username -h localhost -Fc mydb > backup.dump
# 备份特定表
pg_dump -U username -h localhost -t users mydb > users_backup.sql
# 只备份数据
pg_dump -U username -h localhost --data-only mydb > data_only.sql
# 只备份结构
pg_dump -U username -h localhost --schema-only mydb > schema_only.sql使用 pg_restore 恢复
# 从 SQL 文件恢复
psql -U username -h localhost -d mydb < backup.sql
# 从压缩文件恢复
pg_restore -U username -h localhost -d mydb backup.dump
# 创建数据库并恢复
createdb -U username newdb
pg_restore -U username -h localhost -d newdb backup.dump逻辑备份脚本
#!/bin/bash
# 自动备份脚本
BACKUP_DIR="/var/backups/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
DB_USER="postgres"
mkdir -p $BACKUP_DIR
pg_dump -U $DB_USER -h localhost -Fc $DB_NAME > $BACKUP_DIR/${DB_NAME}_${DATE}.dump
# 删除7天前的备份
find $BACKUP_DIR -name "*.dump" -mtime +7 -delete
echo "Backup completed: ${DB_NAME}_${DATE}.dump"物理备份 (使用 pg_basebackup)
# 创建基础备份
pg_basebackup -U postgres -h localhost -D /var/lib/postgresql/backup -Fp -Xs -P
# 恢复时停止服务,清理数据目录,复制备份文件,重启服务性能调优基础
查看系统状态
-- 查看当前连接
SELECT * FROM pg_stat_activity;
-- 查看表大小
SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- 查看索引使用情况
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
-- 查看慢查询
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;配置参数调优
# 内存配置
shared_buffers = 256MB # 通常设置为系统内存的 25%
work_mem = 4MB # 单个查询可用的内存
maintenance_work_mem = 64MB # 维护操作内存
effective_cache_size = 1GB # 操作系统缓存大小
# 检查点配置
checkpoint_completion_target = 0.9
wal_buffers = 16MB
max_wal_size = 1GB
min_wal_size = 80MB
# 查询规划器
random_page_cost = 1.1 # SSD 设为 1.1,HDD 设为 4.0
effective_io_concurrency = 200 # SSD 设为 200,HDD 设为 2索引优化
-- 查看未使用的索引
SELECT schemaname, tablename, indexname
FROM pg_stat_user_indexes
WHERE idx_scan = 0;
-- 查看重复索引
SELECT pg_size_pretty(sum(pg_relation_size(indexrelid))) as size,
array_agg(indexrelid::regclass) as indexes
FROM pg_index
GROUP BY indrelid, indkey
HAVING count(*) > 1;
-- EXPLAIN 分析查询
EXPLAIN ANALYZE SELECT * FROM users WHERE name = '张三';表优化
-- 重新组织表 (VACUUM)
VACUUM users;
-- 完全清理表
VACUUM FULL users;
-- 重新建立索引
REINDEX TABLE users;
-- 分析表统计信息
ANALYZE users;常用命令总结
psql 命令
# 连接数据库
psql -U username -d dbname -h host -p port
# 执行 SQL 文件
psql -U username -d dbname -f file.sql
# 导出查询结果
psql -U username -d dbname -c "SELECT * FROM users" -o output.txtpsql 内部命令
-- 帮助
\?
-- 列出数据库
\l
-- 切换数据库
\c dbname
-- 列出表
\dt
-- 描述表结构
\d table_name
-- 列出用户
\du
-- 查看查询历史
\s
-- 执行操作系统命令
\! ls -la
-- 退出
\q系统管理命令
# 查看 PostgreSQL 进程
ps aux | grep postgres
# 查看日志
tail -f /var/log/postgresql/postgresql-15-main.log
# 检查配置文件语法
postgres -C config_file
# 重新加载配置
pg_ctl reload -D /var/lib/postgresql/15/main故障排除
常见问题
连接被拒绝
- 检查服务是否启动:
sudo systemctl status postgresql - 检查监听地址配置
- 检查防火墙设置
- 检查服务是否启动:
权限不足
-- 检查用户权限 SELECT * FROM information_schema.role_table_grants WHERE grantee = 'username'; -- 授予权限 GRANT ALL PRIVILEGES ON DATABASE mydb TO username;磁盘空间不足
-- 查看数据库大小 SELECT pg_size_pretty(pg_database_size('mydb')); -- 查看表大小 SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) FROM pg_tables ORDER BY pg_total_relation_size DESC LIMIT 10;查询性能问题
-- 启用查询统计 CREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- 查看慢查询 SELECT query, calls, total_time/calls as avg_time FROM pg_stat_statements ORDER BY total_time DESC LIMIT 5;恢复数据库
# 停止服务 sudo systemctl stop postgresql # 清理数据目录 sudo rm -rf /var/lib/postgresql/15/main/* # 从备份恢复 sudo -u postgres pg_restore -C -d postgres /path/to/backup.dump # 启动服务 sudo systemctl start postgresql
监控和维护
-- 查看当前活动连接
SELECT datname, usename, client_addr, state, query_start
FROM pg_stat_activity
WHERE state != 'idle';
-- 查看锁定情况
SELECT blocked_locks.pid as blocked_pid,
blocked_activity.usename as blocked_user,
blocking_locks.pid as blocking_pid,
blocking_activity.usename as blocking_user,
blocked_activity.query as blocked_statement
FROM pg_locks blocked_locks
JOIN pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN 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_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;扩展和插件
-- 查看已安装扩展
SELECT * FROM pg_extension;
-- 安装常用扩展
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- 查询统计
CREATE EXTENSION IF NOT EXISTS uuid-ossp; -- UUID 支持
CREATE EXTENSION IF NOT EXISTS postgis; -- 地理信息支持
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- 模糊匹配这个指南涵盖了 PostgreSQL 的基本安装、配置、使用和维护。如果你在使用过程中遇到特定问题,请提供详细的错误信息以获得更精确的帮助。


评论 (0)