Skip to content

Commit c62dcb2

Browse files
author
xiongcc
committed
添加第20章:How to use pg_restore
1 parent b8550d8 commit c62dcb2

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

How to use pg_restore.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# How to use pg_restore
2+
3+
今天,我们将分享一些使用 `pg_restore` 从转储文件中恢复数据库 (或仅恢复其中一部分) 的技巧。
4+
文档地址:https://postgresql.org/docs/current/app-pgrestore.html
5+
6+
## 并行化与单表限制
7+
8+
当处理以"目录"格式 (`-Fd`) 创建的转储文件时,你可以使用 `-j` (`--jobs`) 选项,通过运行多个 `pg_restore` 工作进程来加速恢复过程。但是,如果有一个或几个大表,这种并行化并不会有帮助 — 单表的转储或恢复不支持并行化。在第 8 天的 [pg_dump](https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/blob/main/0008_how_to_speed_up_pg_dump.md) 系列中,我们讨论过这个问题。
9+
10+
例如,如果你创建了一个标准的 `pgbench` 数据库 (如 `pgbench -i -s1000`),你会发现并行化对转储和恢复都没有太大帮助,因为大部分数据都存储在单个表 `pgbench_accounts` 中。但是,如果你使用了分区 (PG13+ 支持,`pgbench -i -s1000 --partitions=16`),你会发现并行化可以加速转储和恢复步骤。
11+
12+
## 原子恢复
13+
14+
默认情况下,`pg_restore` 不会在出现错误时停止。这可能会让人感到意外,因为我们已经习惯了 Postgres 中的更**严格**的行为。这也可能导致数据库只部分恢复,但这一点被忽视了。要切换到**严格**模式,请使用 `-e` (`--exit-on-error`)。此外,将恢复过程包裹在一个事务中可能也很有帮助,使用选项 `-1` (`--single-transaction`)。
15+
16+
## 详细信息
17+
18+
要查看恢复的进度和详细信息,请使用 `--verbose` 选项。
19+
20+
## 模式与数据分离
21+
22+
你可以从两个不同的角度来查看你的转储文件,两者都提供了高层次结构化转储的方法。
23+
24+
首先,你可以区分模式和数据 — 使用以下选项:
25+
26+
- `-s` (`--schema-only`) — 仅恢复模式。
27+
- `-a` (`--data-only`) — 仅恢复数据 (当然,模式必须已经存在)。
28+
29+
有趣的是,对于转储来说,这种 "模式 + 数据" 的分离在恢复时间和结果质量方面并不是最有效的:索引是模式的一部分,但如果你先创建索引,然后再加载数据,加载过程会变得更慢,并且索引的质量也会变差。如果在加载数据之后构建索引,效果会更好。
30+
31+
因此,有第二种查看转储结构的方式,这种方式对应于完整恢复过程的常规顺序:
32+
33+
- "pre-data" — 模式定义 (不包括索引、约束、触发器和规则)。
34+
- "data" — 表数据。
35+
- "post-data" — 索引、约束、触发器和规则。
36+
37+
`--section` 选项允许你仅运行恢复过程中的其中一个步骤。这可能会在你想要在各步骤之间执行其他操作时很有帮助,或者你想为不同步骤使用不同的并行化级别 (`-j`)。
38+
39+
## 细粒度控制
40+
41+
还有一种方法可以实现更细粒度的控制。
42+
43+
对于以 "目录" 格式 (`-Fd`) 创建的转储,你可以控制恢复的内容。为此,有两个方便的选项:`-l` 列出内容,`-L` 过滤你需要的内容。例如,考虑以下例子:
44+
45+
```bash
46+
pgbench -i -s100 test --partitions 16
47+
pg_dump -f dump1 -j8 -Fd test
48+
```
49+
50+
现在我们可以使用 `-l` (`--list`) 快速列出转储的内容:
51+
52+
```bash
53+
❯ pg_restore -l dump1
54+
;
55+
; Archive created at 2023-10-15 22:00:43 PDT
56+
; dbname: test
57+
; TOC Entries: 94
58+
; Compression: -1
59+
; Dump Version: 1.14-0
60+
; Format: DIRECTORY
61+
; Integer: 4 bytes
62+
; Offset: 8 bytes
63+
; Dumped from database version: 15.4 (Homebrew)
64+
; Dumped by pg_dump version: 15.4 (Homebrew)
65+
;
66+
...
67+
```
68+
69+
如果我们想要恢复除索引之外的所有内容,我们首先需要准备一个包含转储中所有对象的"列表"文件,但不包括约束和索引:
70+
71+
```bash
72+
❯ pg_restore -l dump1 \
73+
| grep -v INDEX \
74+
| grep -v CONSTRAINT \
75+
> no_indexes.list
76+
```
77+
78+
然后使用 `-L` (`--use-list`) 选项指定这个列表文件:
79+
80+
```bash
81+
❯ psql -c 'create database restored'
82+
CREATE DATABASE
83+
❯ pg_restore -j8 -L no_indexes.list --dbname=restored dump1
84+
```
85+
86+
我们可以看到,恢复后的表没有主键或索引:
87+
88+
```sql
89+
❯ psql restored -c '\d pgbench_accounts_1'
90+
Table "public.pgbench_accounts_1"
91+
Column | Type | Collation | Nullable | Default
92+
----------+---------------+-----------+----------+---------
93+
aid | integer | | not null |
94+
bid | integer | | |
95+
abalance | integer | | |
96+
filler | character(84) | | |
97+
Partition of: pgbench_accounts FOR VALUES FROM (MINVALUE) TO (625001)
98+
```
99+
100+
## 权限、属主等
101+
102+
在某些情况下,当在不同环境或集群之间复制或移动架构和数据时,以下选项可以非常有帮助 (这些选项的名称即其含义):
103+
104+
- `--no-owner`
105+
- `--no-privileges`
106+
- `--no-security-labels`
107+
- `--no-publications`
108+
- `--no-subscriptions`
109+
- `--no-tablespaces`
110+
111+
然而,如果原始数据库中使用了RLS (行级安全),没有一个选项可以跳过恢复转储中包含的 `CREATE POLICY` 查询。在这种情况下,我们需要使用前述的细粒度控制方法来移除 `CREATE POLICY` 命令。
112+
113+
因此,当在不同环境之间移动架构和数据时,从转储中恢复的可能步骤如下:
114+
115+
```bash
116+
pg_restore --list /path/to/dump \
117+
| grep -v POLICY \
118+
> dump-no-policies.list
119+
120+
pg_restore \
121+
--jobs=8 \
122+
--dbname=${DBNAME} \
123+
--use-list=./dump-no-policies.list \
124+
--no-owner \
125+
--no-privileges \
126+
--no-security-labels \
127+
--no-publications \
128+
--no-subscriptions \
129+
--no-tablespaces \
130+
--verbose \
131+
--exit-on-error \
132+
/path/to/dump
133+
```
134+
135+
## 附录
136+
137+
很多人 (包括我) 常常忘记这一步 — 实际上,它应该成为 `pg_restore` 的默认行为,但事实并非如此:
138+
139+
在运行 `pg_restore` 之后,不要忘记:
140+
141+
- 收集统计信息 (除非你想等待 `autovacuum` 来做这件事) — `ANALYZE`
142+
- 构建可见性映射 — 执行 `VACUUM`
143+
144+
因此,记得运行 `VACUUM ANALYZE`。也可以并行化:`vacuumdb --jobs=$N`

0 commit comments

Comments
 (0)