2026-04-09 01:28:15 +08:00

31 KiB
Raw Blame History

PostgreSQL 实战指南

目录

  1. PostgreSQL 介绍
  2. PostgreSQL 安装
  3. PostgreSQL 管理
  4. PostgreSQL 体系架构
  5. PostgreSQL 备份还原
  6. 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 ACIDInnoDB
并发控制 MVCC MVCCInnoDB
数据类型 丰富 基础
索引类型 多样 较少
扩展性 强大 一般
复制 流复制/逻辑复制 主从复制/GTID
性能 复杂查询快 简单查询快
许可证 BSD GPL

2. PostgreSQL 安装

2.1 环境要求

  • 操作系统LinuxCentOS/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 机制

WALWrite Ahead Logging预写日志确保数据持久性

  1. 事务提交时,先写 WAL
  2. WAL 写入磁盘后,返回成功
  3. 后台将数据写入磁盘

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年