144 lines
4.3 KiB
Markdown
144 lines
4.3 KiB
Markdown
---
|
||
title: 逻辑备份
|
||
type: concept
|
||
tags: [backup, postgresql, database]
|
||
date: 2025-12-29
|
||
---
|
||
|
||
# 逻辑备份
|
||
|
||
## Definition
|
||
逻辑备份是通过数据库工具导出数据为 SQL 语句或文本格式,而非直接复制物理数据文件。与物理备份相比,逻辑备份具有跨平台迁移能力强、不依赖特定存储格式的优势。
|
||
|
||
## PostgreSQL Logical Backup: pg_dump
|
||
|
||
### Core Command
|
||
```bash
|
||
# 基本语法
|
||
pg_dump -U username -d database_name > backup.sql
|
||
|
||
# Docker 环境(推荐)
|
||
docker exec zipline_postgres pg_dump -U zipline -d zipline > backup.sql
|
||
|
||
# 压缩格式(节省空间)
|
||
docker exec zipline_postgres pg_dump -U zipline -d zipline | gzip > backup.sql.gz
|
||
|
||
# 指定格式(自定义)
|
||
docker exec zipline_postgres pg_dump -U zipline -d zipline -Fc > backup.dump
|
||
```
|
||
|
||
### pg_dump Formats
|
||
|
||
| 格式 | 选项 | 说明 | 恢复灵活性 |
|
||
|------|------|------|------------|
|
||
| Plain SQL | `-Fp`(默认) | 纯文本 SQL,可跨版本 | 高(标准 SQL) |
|
||
| Custom | `-Fc` | 二进制压缩格式 | 中(需 pg_restore) |
|
||
| Directory | `-Fd` | 并行导出,多文件 | 高 |
|
||
| TAR | `-Ft` | TAR 归档格式 | 中 |
|
||
|
||
## Logical vs Physical Backup
|
||
|
||
| 特性 | 逻辑备份 | 物理备份 |
|
||
|------|----------|----------|
|
||
| 备份方式 | SQL 导出 | 直接复制数据文件 |
|
||
| 热备份 | ✅ 支持 | ⚠️ 需要额外配置 |
|
||
| 数据损坏风险 | 无 | 有(热备份时) |
|
||
| 跨版本迁移 | ✅ 完全支持 | ❌ 通常不行 |
|
||
| 备份速度 | 慢 | 快 |
|
||
| 恢复速度 | 慢 | 快 |
|
||
| 增量备份 | ❌ 不支持 | ✅ 支持 |
|
||
| 适用场景 | 跨平台迁移、小数据量 | 大数据量、灾难恢复 |
|
||
|
||
## Synology NAS Backup Script
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# Zipline Stack Backup Script
|
||
|
||
BACKUP_DIR="/volume1/docker/zipline-stack/backups"
|
||
PG_CONTAINER="zipline_postgres"
|
||
PG_USER="zipline"
|
||
PG_DB="zipline"
|
||
RETENTION_DAYS=30
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
|
||
mkdir -p "$BACKUP_DIR"
|
||
|
||
echo "[$DATE] 开始备份 Postgres..."
|
||
|
||
# pg_dump 逻辑备份(热备份)
|
||
# 注意:这里不直接备份 /var/lib/postgresql/data 目录
|
||
# 热备份该目录会导致数据损坏
|
||
docker exec "$PG_CONTAINER" pg_dump -U "$PG_USER" -d "$PG_DB" | gzip > "$BACKUP_DIR/db_$DATE.sql.gz"
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "[$DATE] 数据库备份成功: db_$DATE.sql.gz"
|
||
else
|
||
echo "[$DATE] !!! 数据库备份失败 !!!"
|
||
exit 1
|
||
fi
|
||
|
||
# 清理旧备份
|
||
find "$BACKUP_DIR" -name "db_*.sql.gz" -mtime +$RETENTION_DAYS -delete
|
||
echo "[$DATE] 已清理超过 $RETENTION_DAYS 天的旧备份"
|
||
|
||
echo "[$DATE] 备份流程结束。"
|
||
```
|
||
|
||
## Key Principles
|
||
|
||
1. **禁止热备份物理目录**
|
||
> "不直接备份 /var/lib/postgresql/data 目录,因为热备份该目录会导致数据损坏"
|
||
|
||
2. **与文件备份配合**
|
||
- 逻辑备份:pg_dump → SQL 文件
|
||
- 文件备份:Hyper Backup → MinIO 数据目录
|
||
- 两者需尽量接近时间点备份
|
||
|
||
3. **自动化**
|
||
- Synology Task Scheduler:每日凌晨 3:00
|
||
- 日志输出:`>> backup.log 2>&1`
|
||
|
||
## "脑体分离" Architecture Challenge
|
||
|
||
[[Zipline]] 的备份挑战在于"脑体分离":
|
||
|
||
```
|
||
大脑 (PostgreSQL) 身体 (MinIO)
|
||
│ │
|
||
▼ ▼
|
||
"文件A的ID是123, 实际存储了 a.jpg
|
||
位于MinIO的/bucket/a.jpg"
|
||
│ │
|
||
└──────── 需同步备份 ────────┘
|
||
```
|
||
|
||
**风险**:如果在 10:00 备份了数据库,10:05 备份了 MinIO,但这 5 分钟内上传了新文件,恢复时就会出现"数据库找不到文件"或"文件没记录"的幽灵数据。
|
||
|
||
**缓解方案**:尽量缩短两个备份的时间间隔,使用自动化脚本同时触发。
|
||
|
||
## Restore Commands
|
||
|
||
```bash
|
||
# 恢复 Plain SQL
|
||
gunzip < backup.sql.gz | psql -U username -d database_name
|
||
|
||
# 恢复 Custom Format
|
||
pg_restore -U username -d database_name -c backup.dump
|
||
|
||
# Docker 环境
|
||
cat backup.sql.gz | gunzip | docker exec -i zipline_postgres psql -U zipline -d zipline
|
||
```
|
||
|
||
## Connections
|
||
- [[PostgreSQL]] ← backed up by ← [[逻辑备份]]
|
||
- [[Zipline]] ← metadata stored in ← [[PostgreSQL]]
|
||
- [[pg_dump]] ← tool for ← [[逻辑备份]]
|
||
- [[数据一致性]] ← challenge of ← [[逻辑备份]] + 文件备份
|
||
|
||
## Related Concepts
|
||
- [[增量备份]]
|
||
- [[全盘镜像备份]]
|
||
- [[数据一致性]]
|
||
- [[备份脚本]]
|