1166 lines
31 KiB
Markdown
1166 lines
31 KiB
Markdown
# PostgreSQL 实战指南
|
||
|
||
## 目录
|
||
|
||
1. [PostgreSQL 介绍](#1-postgresql-介绍)
|
||
2. [PostgreSQL 安装](#2-postgresql-安装)
|
||
3. [PostgreSQL 管理](#3-postgresql-管理)
|
||
4. [PostgreSQL 体系架构](#4-postgresql-体系架构)
|
||
5. [PostgreSQL 备份还原](#5-postgresql-备份还原)
|
||
6. [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 | 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)
|
||
|
||
```bash
|
||
# 安装 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)
|
||
|
||
```bash
|
||
# 安装 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 源码编译安装
|
||
|
||
```bash
|
||
# 安装依赖
|
||
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 安装
|
||
|
||
```bash
|
||
# 拉取镜像
|
||
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 基础配置
|
||
|
||
```bash
|
||
# 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 配置
|
||
|
||
```bash
|
||
# 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 启动和停止
|
||
|
||
```bash
|
||
# 服务方式(使用 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 连接和基本操作
|
||
|
||
```bash
|
||
# 连接数据库
|
||
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 数据库操作
|
||
|
||
```bash
|
||
# 创建数据库
|
||
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 表操作
|
||
|
||
```bash
|
||
# 创建表
|
||
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 索引操作
|
||
|
||
```bash
|
||
# 创建索引
|
||
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 用户和权限管理
|
||
|
||
```bash
|
||
# 创建用户
|
||
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 视图操作
|
||
|
||
```bash
|
||
# 创建视图
|
||
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 函数和存储过程
|
||
|
||
```bash
|
||
# 创建函数
|
||
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 触发器
|
||
|
||
```bash
|
||
# 创建触发器函数
|
||
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 分区表
|
||
|
||
```bash
|
||
# 创建范围分区表
|
||
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 性能分析
|
||
|
||
```bash
|
||
# 查看慢查询
|
||
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 事务隔离级别
|
||
|
||
```sql
|
||
-- 查看当前隔离级别
|
||
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)预写日志,确保数据持久性:
|
||
|
||
1. 事务提交时,先写 WAL
|
||
2. WAL 写入磁盘后,返回成功
|
||
3. 后台将数据写入磁盘
|
||
|
||
#### 4.7.2 检查点
|
||
|
||
```sql
|
||
-- 手动执行检查点
|
||
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)
|
||
|
||
```bash
|
||
# 备份单个数据库
|
||
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)
|
||
|
||
```bash
|
||
# 还原数据库
|
||
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)
|
||
|
||
```bash
|
||
# 基础物理备份
|
||
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 归档
|
||
|
||
```bash
|
||
# 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 执行基础备份
|
||
|
||
```bash
|
||
pg_basebackup -U postgres -D /backup/base -Ft -z -P
|
||
```
|
||
|
||
#### 5.5.3 恢复配置
|
||
|
||
```bash
|
||
# 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 启动恢复
|
||
|
||
```bash
|
||
# 停止 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 定时备份脚本
|
||
|
||
```bash
|
||
#!/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)
|
||
|
||
```bash
|
||
# 编辑 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 主库配置
|
||
|
||
```bash
|
||
# 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 从库配置
|
||
|
||
```bash
|
||
# 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 创建复制用户
|
||
|
||
```sql
|
||
-- 主库执行
|
||
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 启动从库
|
||
|
||
```bash
|
||
# 从主库基础备份
|
||
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 发布和订阅
|
||
|
||
```sql
|
||
-- 在发布库创建发布
|
||
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 复制槽
|
||
|
||
```sql
|
||
-- 创建复制槽(逻辑复制必须)
|
||
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 配置
|
||
|
||
```yaml
|
||
# 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
|
||
|
||
```bash
|
||
# 安装 Patroni
|
||
pip install patroni[etcd] etcd
|
||
|
||
# 启动 Patroni
|
||
patroni patroni.yml
|
||
```
|
||
|
||
### 6.5 PgBouncer 连接池
|
||
|
||
```bash
|
||
# 安装 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 读写分离
|
||
|
||
```bash
|
||
# 应用程序配置
|
||
|
||
# 主库(写)
|
||
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 故障转移
|
||
|
||
```sql
|
||
-- 手动故障转移(从库执行)
|
||
SELECT pg_promote();
|
||
|
||
-- 查看复制状态
|
||
SELECT * FROM pg_stat_replication;
|
||
|
||
-- 查看复制延迟
|
||
SELECT now() - pg_last_xact_replay_timestamp() AS replication_lag;
|
||
```
|
||
|
||
### 6.8 监控指标
|
||
|
||
```sql
|
||
-- 查看连接数
|
||
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年*
|