PostgreSQL 实战指南
目录
- PostgreSQL 介绍
- PostgreSQL 安装
- PostgreSQL 管理
- PostgreSQL 体系架构
- PostgreSQL 备份还原
- PostgreSQL 高可用
1. PostgreSQL 介绍
1.1 什么是 PostgreSQL
PostgreSQL 是一个功能强大的开源对象关系型数据库系统(ORDBMS),支持 SQL 标准并具有丰富的企业级特性。作为最先进的开源数据库,PostgreSQL 以其可靠性、数据完整性和扩展性著称。
1.2 PostgreSQL 特点
| 特性 |
说明 |
| 开源免费 |
完全开源,BSD/MIT 许可证 |
| ACID 完整 |
完全支持 ACID 事务特性 |
| MVCC |
多版本并发控制,支持高并发 |
| 丰富数据类型 |
支持数组、JSON、UUID、几何类型等 |
| 索引类型 |
支持 B-tree、Hash、GIN、GiST、BRIN 等 |
| 扩展性 |
支持自定义函数、操作符、数据类型 |
| 外键约束 |
完整的外键约束支持 |
| 视图 |
支持物化视图、普通视图 |
| 触发器 |
支持行级和语句级触发器 |
| 存储过程 |
支持存储过程(多种语言) |
| 分区表 |
支持范围分区、列表分区、哈希分区 |
| 复制 |
支持流复制、逻辑复制 |
| 集群 |
支持 Citus 分布式集群 |
1.3 PostgreSQL 应用场景
| 场景 |
说明 |
| 企业应用 |
ERP、CRM 等企业级应用数据库 |
| GIS 应用 |
PostGIS 扩展支持地理信息系统 |
| 数据仓库 |
分析型数据库,大数据处理 |
| Web 应用 |
LAMP/LEMP 架构数据存储 |
| 金融系统 |
对事务要求严格的系统 |
| 科研数据 |
科研数据存储和分析 |
1.4 PostgreSQL 与 MySQL 对比
| 特性 |
PostgreSQL |
MySQL |
| 事务支持 |
完整 ACID |
ACID(InnoDB) |
| 并发控制 |
MVCC |
MVCC(InnoDB) |
| 数据类型 |
丰富 |
基础 |
| 索引类型 |
多样 |
较少 |
| 扩展性 |
强大 |
一般 |
| 复制 |
流复制/逻辑复制 |
主从复制/GTID |
| 性能 |
复杂查询快 |
简单查询快 |
| 许可证 |
BSD |
GPL |
2. PostgreSQL 安装
2.1 环境要求
- 操作系统:Linux(CentOS/Ubuntu/Debian)、macOS、Windows
- 内存:至少 1GB(生产环境建议 4GB+)
- 磁盘:至少 100GB
2.2 YUM 安装(CentOS/RHEL)
# 安装 PostgreSQL Yum 源
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 安装 PostgreSQL 服务器和客户端
yum install -y postgresql15-server postgresql15
# 初始化数据库
/usr/pgsql-15/bin/postgresql-15-setup initdb
# 启动服务
systemctl start postgresql-15
systemctl enable postgresql-15
# 检查服务状态
systemctl status postgresql-15
2.3 APT 安装(Debian/Ubuntu)
# 安装 PostgreSQL APT 源
sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
# 更新并安装
apt update
apt install -y postgresql-15 postgresql-client-15
# 启动服务
systemctl start postgresql
systemctl enable postgresql
2.4 源码编译安装
# 安装依赖
yum install -y gcc make libxml2 libuuid openssl readline zlib
# 下载源码
wget https://ftp.postgresql.org/pub/source/v15.4/postgresql-15.4.tar.gz
tar -zxf postgresql-15.4.tar.gz
cd postgresql-15.4
# 配置
./configure --prefix=/usr/local/pgsql-15 \
--with-openssl \
--with-readline \
--with-uuid=libuuid \
--with-libxml \
--with-zlib
# 编译安装
make -j4
make install
# 创建用户
useradd -m -s /bin/bash postgres
mkdir -p /usr/local/pgsql-15/data
chown -R postgres:postgres /usr/local/pgsql-15
# 切换用户初始化
su - postgres
/usr/local/pgsql-15/bin/initdb -D /usr/local/pgsql-15/data
# 启动数据库
/usr/local/pgsql-15/bin/pg_ctl -D /usr/local/pgsql-15/data -l /usr/local/pgsql-15/logfile start
2.5 Docker 安装
# 拉取镜像
docker pull postgres:15
# 运行容器
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=your_password \
-e POSTGRES_USER=admin \
-e POSTGRES_DB=mydb \
-p 5432:5432 \
-v /data/postgres/data:/var/lib/postgresql/data \
postgres:15
# 使用配置文件启动
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=your_password \
-v /data/postgres/postgresql.conf:/etc/postgresql/postgresql.conf \
-v /data/postgres/data:/var/lib/postgresql/data \
postgres:15 -c config-file=/etc/postgresql/postgresql.conf
2.6 基础配置
# postgresql.conf 主要配置
# 连接配置
listen_addresses = '*'
port = 5432
max_connections = 200
# 内存配置
shared_buffers = 4GB
effective_cache_size = 12GB
work_mem = 256MB
maintenance_work_mem = 1GB
# 持久化配置
wal_level = replica
max_wal_size = 1GB
min_wal_size = 80MB
# 日志配置
log_destination = 'stderr'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_statement = 'ddl'
log_min_duration_statement = 1000
# 复制配置
wal_sender_timeout = 60s
wal_receiver_timeout = 60s
# 客户端连接配置
authentication_timeout = 1min
password_encryption = scram-sha-256
2.7 pg_hba.conf 配置
# pg_hba.conf - 客户端认证
# 本地连接
local all all trust
# IPv4 本地回环
host all all 127.0.0.1/32 scram-sha-256
# IPv6 本地回环
host all all ::1/128 scram-sha-256
# 允许特定网段
host all all 192.168.1.0/24 scram-sha-256
# 允许所有网段(生产环境谨慎)
# host all all 0.0.0.0/0 scram-sha-256
# 复制连接
local replication all trust
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256
host replication all 192.168.1.0/24 scram-sha-256
2.8 启动和停止
# 服务方式(使用 RPM/APT 安装)
systemctl start postgresql-15
systemctl stop postgresql-15
systemctl restart postgresql-15
systemctl status postgresql-15
# 手动方式
pg_ctl -D /var/lib/pgsql/15/data start
pg_ctl -D /var/lib/pgsql/15/data stop
# 连接数据库
psql -U postgres
psql -h localhost -U postgres -d mydb
3. PostgreSQL 管理
3.1 连接和基本操作
# 连接数据库
psql -U username -d database_name
psql -h hostname -p 5432 -U username -d database_name
# 常用命令
\l # 列出所有数据库
\d # 列出当前数据库的所有表
\d table_name # 查看表结构
\du # 列出所有用户
\di # 列出所有索引
\dv # 列出所有视图
\dt # 列出所有表
\db # 列出所有表空间
\x # 展开显示
\? # 帮助
\q # 退出
3.2 数据库操作
# 创建数据库
CREATE DATABASE mydb;
# 创建数据库(指定所有者、编码)
CREATE DATABASE mydb
OWNER postgres
ENCODING 'UTF8'
TEMPLATE template0;
# 删除数据库
DROP DATABASE mydb;
# 修改数据库
ALTER DATABASE mydb RENAME TO newdb;
ALTER DATABASE mydb SET work_mem = '256MB';
# 切换数据库
\c mydb
\connect mydb
3.3 表操作
# 创建表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
age INTEGER CHECK (age >= 0),
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
# 创建表(带约束)
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT valid_amount CHECK (total_amount >= 0)
);
# 查看表结构
\d users
# 修改表
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
ALTER TABLE users DROP COLUMN phone;
ALTER TABLE users RENAME COLUMN email TO user_email;
ALTER TABLE users ALTER COLUMN age SET DEFAULT 18;
ALTER TABLE users ALTER COLUMN age DROP DEFAULT;
ALTER TABLE users ADD CONSTRAINT unique_email UNIQUE (user_email);
# 删除表
DROP TABLE users;
DROP TABLE IF EXISTS users;
3.4 索引操作
# 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_users_created ON users(created_at DESC);
# 创建唯一索引
CREATE UNIQUE INDEX idx_users_username ON users(username);
# 创建复合索引
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
# 创建部分索引
CREATE INDEX idx_orders_active ON orders(user_id) WHERE status = 'active';
# 创建表达式索引
CREATE INDEX idx_users_lower_email ON users(LOWER(email));
# 查看索引
\d users
SELECT * FROM pg_indexes WHERE tablename = 'users';
# 删除索引
DROP INDEX idx_users_email;
3.5 用户和权限管理
# 创建用户
CREATE USER username WITH PASSWORD 'password';
# 创建超级用户
CREATE USER admin WITH SUPERUSER PASSWORD 'password';
# 修改用户
ALTER USER username WITH PASSWORD 'newpassword';
ALTER USER username VALID UNTIL '2025-01-01';
ALTER USER username CREATEDB;
ALTER USER username CREATEROLE;
# 删除用户
DROP USER username;
# 创建角色
CREATE ROLE readonly;
CREATE ROLE readwrite;
# 角色授权
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO readwrite;
# 默认权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO readonly;
# 撤销权限
REVOKE ALL PRIVILEGES ON TABLE users FROM username;
REVOKE INSERT ON ALL TABLES IN SCHEMA public FROM readwrite;
# 查看权限
\du username
3.6 视图操作
# 创建视图
CREATE VIEW user_orders AS
SELECT u.username, o.id, o.total_amount, o.status, o.created_at
FROM users u
JOIN orders o ON u.id = o.user_id;
# 创建物化视图
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT DATE_TRUNC('month', created_at) AS month, SUM(total_amount) AS total
FROM orders
GROUP BY DATE_TRUNC('month', created_at);
# 刷新物化视图
REFRESH MATERIALIZED VIEW monthly_sales;
# 删除视图
DROP VIEW user_orders;
DROP MATERIALIZED VIEW monthly_sales;
3.7 函数和存储过程
# 创建函数
CREATE OR REPLACE FUNCTION get_user_count()
RETURNS INTEGER AS $$
BEGIN
RETURN (SELECT COUNT(*) FROM users);
END;
$$ LANGUAGE plpgsql;
# 创建存储过程( PostgreSQL 11+)
CREATE OR REPLACE PROCEDURE update_user_status(user_id INT, new_status INT)
LANGUAGE plpgsql AS $$
BEGIN
UPDATE users SET status = new_status, updated_at = CURRENT_TIMESTAMP
WHERE id = user_id;
END;
$$;
# 调用存储过程
CALL update_user_status(1, 2);
3.8 触发器
# 创建触发器函数
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
# 创建触发器
CREATE TRIGGER update_users_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_timestamp();
# 查看触发器
\dT+ users
# 删除触发器
DROP TRIGGER update_users_timestamp ON users;
3.9 分区表
# 创建范围分区表
CREATE TABLE orders (
id BIGSERIAL,
user_id INTEGER NOT NULL,
total_amount DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) PARTITION BY RANGE (created_at);
# 创建分区
CREATE TABLE orders_2024 PARTITION OF orders
FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
CREATE TABLE orders_2025 PARTITION OF orders
FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');
# 创建列表分区
CREATE TABLE products (
id SERIAL,
name VARCHAR(100),
category VARCHAR(50)
) PARTITION BY LIST (category);
CREATE TABLE products_electronics PARTITION OF products
FOR VALUES IN ('electronics', 'computers');
CREATE TABLE products_clothing PARTITION OF products
FOR VALUES IN ('clothing', 'fashion');
3.10 性能分析
# 查看慢查询
SELECT query, calls, mean_time, total_time
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
# 查看表大小
SELECT relname, pg_size_pretty(pg_total_relation_size(relid))
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
# 查看索引使用情况
SELECT indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
# 分析表
ANALYZE users;
# 清理缓存
DISCARD ALL;
4. PostgreSQL 体系架构
4.1 架构概述
PostgreSQL 采用进程/线程混合架构,主要包括:
┌─────────────────────────────────────────────────────┐
│ PostgreSQL 进程结构 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ Postmaster │ ← 主进程(父进程) │
│ │ (PID 1234) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────┼─────┬─────────────┐ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌────┐ ┌────┐ ┌──────┐ ┌──────┐ │
│ │Writer│ │Wal │ │Check-│ │Auto-│ │
│ │Writer│ │Writer│ │pointer│ │vacuum│ │
│ └────┘ └────┘ └──────┘ └──────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Client Connections │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │postgres│ │postgres│ │postgres│ ... │ │
│ │ │(PID 1) │ │(PID 2) │ │(PID 3) │ │ │
│ │ └──────┘ └──────┘ └──────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
4.2 进程说明
| 进程 |
说明 |
| Postmaster |
主进程,监听连接请求,创建子进程 |
| Writer |
负责将数据写入磁盘 |
| Wal Writer |
负责将 WAL 写入磁盘 |
| Checkpointer |
检查点进程,触发检查点 |
| Autovacuum |
自动 vacuum 进程 |
| Archiver |
WAL 归档进程 |
| Stats Collector |
统计信息收集进程 |
| Bgwriter |
后台写进程 |
| Client Process |
每个客户端连接对应的服务进程 |
4.3 内存结构
┌─────────────────────────────────────────────────────┐
│ PostgreSQL 内存结构 │
├─────────────────────────────────────────────────────┤
│ │
│ 共享内存(Shared Memory) │
│ ┌─────────────────────────────────────────────┐ │
│ │ shared_buffers ← 数据缓存 │ │
│ │ wal_buffers ← WAL 缓冲区 │ │
│ │ commit_timestamp buffers │ │
│ │ locks ← 锁管理 │ │
│ │ predicate_locks ← 谓词锁 │ │
│ │ transaction logs ← 事务日志 │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ 进程内存(Process Memory) │
│ ┌─────────────────────────────────────────────┐ │
│ │ work_mem ← 排序/哈希操作内存 │ │
│ │ maintenance_work_mem ← 维护操作内存 │ │
│ │ temp_buffers ← 临时表缓存 │ │
│ │ parallel_worker ← 并行工作进程内存 │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
4.4 核心概念
4.4.1 共享内存
| 参数 |
说明 |
shared_buffers |
数据页缓存,建议设置为系统内存的 25% |
wal_buffers |
WAL 缓冲区,默认 16MB |
effective_cache_size |
操作系统缓存估计,影响查询规划 |
4.4.2 进程内存
| 参数 |
说明 |
work_mem |
排序和哈希操作内存,每个操作独立分配 |
maintenance_work_mem |
维护操作(VACUUM、CREATE INDEX)内存 |
temp_buffers |
临时表缓存 |
4.5 存储结构
4.5.1 物理存储
PostgreSQL 数据目录:$PGDATA
$PGDATA/
├── base/ # 表数据文件
│ ├── 12345/ # 数据库 OID
│ │ ├── 12345 # 表文件
│ │ ├── 12345.1 # 表文件(超过 1GB 自动分卷)
│ │ └── 12345_vm # 可见性映射
│ └── ...
├── global/ # 系统表
├── pg_wal/ # WAL 日志
├── pg_xact/ # 事务状态
├── pg_notify/ # LISTEN/NOTIFY
├── pg_serial/ # 可序列化事务
├── pg_subtrans/ # 子事务
├── pg_tblspc/ # 表空间链接
├── pg_dynshmem/ # 动态共享内存
├── pg_replslot/ # 复制槽
├── pg_stat/ # 统计信息
├── pg_stat_tmp/ # 临时统计信息
├── pg_snapshots/ # 导出快照
├── pg_logical/ # 逻辑解码
├── pg_walwriter/ # WAL 写入器
├── pg_conf/ # 配置文件
├── postgresql.conf # 主配置文件
├── pg_hba.conf # 客户端认证
└── pg_ident.conf # 用户映射
4.5.2 逻辑存储
- 表(Table):由行组成的数据集合
- 行(Row):一条记录
- 页(Page):默认 8KB,存储基本单元
- 元组(Tuple):行的物理表示
4.6 事务管理
4.6.1 MVCC 机制
PostgreSQL 使用 MVCC(多版本并发控制)实现事务隔离:
- 每次更新创建新版本,旧版本保留
- 事务通过查看版本号判断可见性
- 读写不冲突,提高并发性能
4.6.2 事务隔离级别
-- 查看当前隔离级别
SHOW transaction_isolation;
-- 设置隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;
| 级别 |
说明 |
脏读 |
不可重复读 |
幻读 |
| READ UNCOMMITTED |
读未提交 |
可能 |
可能 |
可能 |
| READ COMMITTED |
读已提交 |
不可能 |
可能 |
可能 |
| REPEATABLE READ |
可重复读 |
不可能 |
不可能 |
可能 |
| SERIALIZABLE |
串行化 |
不可能 |
不可能 |
不可能 |
4.7 WAL 日志
4.7.1 WAL 机制
WAL(Write Ahead Logging)预写日志,确保数据持久性:
- 事务提交时,先写 WAL
- WAL 写入磁盘后,返回成功
- 后台将数据写入磁盘
4.7.2 检查点
-- 手动执行检查点
CHECKPOINT;
-- 查看检查点统计
SELECT * FROM pg_stat_checkpoints;
4.8 存储引擎
PostgreSQL 使用单一存储引擎(heap),通过不同索引实现不同访问模式:
| 索引类型 |
适用场景 |
| B-tree |
范围查询、排序 |
| Hash |
精确匹配 |
| GiST |
几何、地理数据 |
| GIN |
全文搜索、数组 |
| BRIN |
顺序扫描、大表 |
| SP-GiST |
空间分割 |
5. PostgreSQL 备份还原
5.1 备份类型
| 类型 |
说明 |
工具 |
| SQL 导出 |
逻辑备份,可跨版本 |
pg_dump |
| 物理备份 |
直接复制数据文件 |
pg_basebackup |
| 归档备份 |
增量备份 |
WAL 归档 |
5.2 逻辑备份(pg_dump)
# 备份单个数据库
pg_dump -U postgres -Fc mydb > mydb.dump
pg_dump -U postgres -Fp mydb > mydb.sql
# 备份所有数据库
pg_dumpall -U postgres > all_databases.sql
# 备份指定表
pg_dump -U postgres -t users -t orders mydb > tables.sql
# 备份表结构
pg_dump -U postgres -s mydb > schema.sql
# 备份数据
pg_dump -U postgres -a mydb > data.sql
# 压缩备份
pg_dump -U postgres -Fc mydb > mydb.dump.gz
# 并行备份(PostgreSQL 13+)
pg_dump -U postgres -Fd -j 4 -f backup_dir mydb
5.3 逻辑还原(pg_restore)
# 还原数据库
psql -U postgres -d mydb < mydb.sql
# 还原压缩备份
pg_restore -U postgres -d mydb mydb.dump
# 还原前删除原有对象
pg_restore -U postgres -d mydb --clean mydb.dump
# 还原到新数据库
createdb -U postgres newdb
pg_restore -U postgres -d newdb mydb.dump
# 还原并行备份
pg_restore -U postgres -d mydb -j 4 backup_dir/
5.4 物理备份(pg_basebackup)
# 基础物理备份
pg_basebackup -U postgres -D /backup/base -Ft -z -P
# 流复制备份
pg_basebackup -U postgres -D /backup/base -Xs -P
# 带 WAL 的备份
pg_basebackup -U postgres -D /backup/base -X stream -P
# 备份到远程
pg_basebackup -U postgres -h remote_host -D /backup/base -Xs -P
5.5 PITR(时间点恢复)
5.5.1 配置 WAL 归档
# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /backup/wal/%f && cp %p /backup/wal/%f'
archive_timeout = 300
5.5.2 执行基础备份
pg_basebackup -U postgres -D /backup/base -Ft -z -P
5.5.3 恢复配置
# postgresql.conf 恢复配置
restore_command = 'cp /backup/wal/%f %p'
recovery_target_time = '2024-01-15 10:00:00'
# 创建恢复信号文件
touch /var/lib/pgsql/15/data/recovery.signal
5.5.4 启动恢复
# 停止 PostgreSQL
pg_ctl -D /var/lib/pgsql/15/data stop
# 修改配置后启动
pg_ctl -D /var/lib/pgsql/15/data -l /var/lib/pgsql/15/data/logfile start
5.6 定时备份脚本
#!/bin/bash
# 备份配置
BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
DB_USER="postgres"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 删除 7 天前的备份
find $BACKUP_DIR -type f -mtime +7 -delete
# 执行备份
pg_dump -U $DB_USER -Fc $DB_NAME > $BACKUP_DIR/${DB_NAME}_${DATE}.dump
# 记录日志
echo "[$(date)] Backup completed: ${DB_NAME}_${DATE}.dump" >> /var/log/pg_backup.log
5.7 自动备份(cron)
# 编辑 crontab
crontab -e
# 每天凌晨 2 点执行备份
0 2 * * * /usr/local/bin/backup.sh
# 每天凌晨 2 点和下午 2 点执行备份
0 2,14 * * * /usr/local/bin/backup.sh
6. PostgreSQL 高可用
6.1 高可用方案概述
| 方案 |
说明 |
复杂度 |
延迟 |
| 流复制 |
主从同步复制 |
低 |
低 |
| 逻辑复制 |
表级别复制 |
中 |
低 |
| Patroni + etcd |
自动故障转移 |
高 |
低 |
| PgBouncer |
连接池 + 负载均衡 |
中 |
- |
| Citus |
分布式集群 |
高 |
中 |
6.2 流复制配置
6.2.1 主库配置
# postgresql.conf
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1GB
# 可选:同步复制
synchronous_commit = on
synchronous_standby_names = 'standby1'
6.2.2 从库配置
# postgresql.conf
primary_conninfo = 'host=192.168.1.100 port=5432 user=replica password=replica_pass'
# 可选:只读模式
hot_standby = on
max_standby_streaming_delay = 30s
6.2.3 创建复制用户
-- 主库执行
CREATE USER replica REPLICATION LOGIN PASSWORD 'replica_pass';
-- 配置 pg_hba.conf
host replication replica 192.168.1.0/24 scram-sha-256
6.2.4 启动从库
# 从主库基础备份
pg_basebackup -U postgres -h 192.168.1.100 -D /var/lib/pgsql/15/data -Xs -P
# 启动从库
pg_ctl -D /var/lib/pgsql/15/data -l /var/lib/pgsql/15/data/logfile start
6.3 逻辑复制配置
6.3.1 发布和订阅
-- 在发布库创建发布
CREATE PUBLICATION mypub FOR TABLE users, orders;
-- 在订阅库创建订阅
CREATE SUBSCRIPTION mysub
CONNECTION 'host=192.168.1.100 port=5432 dbname=mydb user=postgres'
PUBLICATION mypub;
6.3.2 复制槽
-- 创建复制槽(逻辑复制必须)
SELECT * FROM pg_create_logical_replication_slot('slot_name', 'pgoutput');
-- 查看复制槽
SELECT * FROM pg_replication_slots;
6.4 Patroni 高可用
6.4.1 Patroni 架构
┌─────────────────────────────────────────────────────┐
│ Patroni 高可用架构 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ etcd 1 │──────│ etcd 2 │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ └──────────┬─────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Patroni Leader │ │
│ │ 192.168.1.100 │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Standby 1│ │ Standby 2│ │
│ │192.168.1│ │192.168.1│ │
│ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────┘
6.4.2 Patroni 配置
# patroni.yml
scope: postgres-cluster
name: postgres-1
etcd:
hosts: 192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379
postgresql:
data_dir: /var/lib/pgsql/15/data
pgpass: /tmp/pgpass
parameters:
wal_level: replica
max_wal_senders: 10
max_replication_slots: 10
hot_standby: on
bootstrap:
dcs: postgresql
method: basebackup
basebackup:
host: 192.168.1.100
user: postgres
restapi:
listen: 192.168.1.100:8008
connect_address: 192.168.1.100:8008
6.4.3 启动 Patroni
# 安装 Patroni
pip install patroni[etcd] etcd
# 启动 Patroni
patroni patroni.yml
6.5 PgBouncer 连接池
# 安装 PgBouncer
yum install pgbouncer -y
# 配置 pgbouncer.ini
[databases]
mydb = host=192.168.1.100 port=5432 dbname=mydb
[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
# 配置 userlist.txt
"postgres" "md5d7f7a8..."
# 启动 PgBouncer
systemctl start pgbouncer
systemctl enable pgbouncer
6.6 读写分离
# 应用程序配置
# 主库(写)
jdbc:postgresql://192.168.1.100:5432/mydb
# 从库(读)
jdbc:postgresql://192.168.1.101:5432/mydb
jdbc:postgresql://192.168.1.102:5432/mydb
# 伪代码:读写分离
def execute_query(sql):
if sql.strip().upper().startswith('SELECT'):
return execute_on_slave(sql)
else:
return execute_on_master(sql)
6.7 故障转移
-- 手动故障转移(从库执行)
SELECT pg_promote();
-- 查看复制状态
SELECT * FROM pg_stat_replication;
-- 查看复制延迟
SELECT now() - pg_last_xact_replay_timestamp() AS replication_lag;
6.8 监控指标
-- 查看连接数
SELECT count(*) FROM pg_stat_activity;
-- 查看慢查询
SELECT query, state, wait_event, query_start
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY query_start DESC;
-- 查看复制延迟
SELECT client_addr, state, lag
FROM pg_stat_replication;
-- 查看锁等待
SELECT * FROM pg_locks WHERE NOT granted;
附录
常用命令速查
| 命令 |
说明 |
psql -U postgres |
连接数据库 |
\l |
列出数据库 |
\d |
列出表 |
\du |
列出用户 |
\x |
展开显示 |
CREATE DATABASE db |
创建数据库 |
DROP DATABASE db |
删除数据库 |
CREATE USER user |
创建用户 |
GRANT ALL ON db |
授权 |
配置文件参数速查
| 参数 |
说明 |
listen_addresses |
监听地址 |
port |
端口 |
max_connections |
最大连接数 |
shared_buffers |
共享缓存 |
work_mem |
工作内存 |
wal_level |
WAL 级别 |
max_wal_senders |
最大 WAL 发送数 |
端口说明
| 端口 |
说明 |
| 5432 |
PostgreSQL 主服务端口 |
| 5433 |
PostgreSQL 主服务(多实例) |
| 6432 |
PgBouncer 连接池端口 |
| 8008 |
Patroni REST API 端口 |
文档创建时间:2024年