meface/docs/article/db/postgresqlrestore.md

331 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Postgresql 备份方式
date: 2020-10-10
author: ac
tags:
- postgresql
categories:
- Database
---
## Postgresql 备份方式
### 1. 数据库备份的分类类型
按备份后的文件类型分为:
- 物理备份(文件系统级别的备份)
- 逻辑备份sql文件或其它特定格式的导出文件
按备份过程中是否停止数据库服务分:
- 热备份:备份过程中数据库服务开启并可供用户访问
- 冷备份:备份过程中停止数据库服务
按备份是否完整分:
- 全量备份:备份整个数据库数据
- 增量备份:备份上一次全量备份后数据库改变的内容
### 2. [SQL Dump](https://www.postgresql.org/docs/9.5/backup-dump.html)(SQL转储)
SQL命令`pg_dump` [`connection-option`...] [`option`...] [`dbname`]
该方法是使用SQL命令生成一个文件当该文件被反馈到服务器时它将以与转储时相同的状态重新创建数据库。
pg_dump是用于备份PostgreSQL数据库的实用程序 。优点:
- 即使同时使用数据库,它也会进行一致的备份。 pg_dump不会阻止其他用户访问数据库读取器或写入器
- pg_dump并不影响数据库工作过程中的其他操作主要是关心pg_dump会不会产生读写锁read lock、write lock但也有例外那就是哪些需要使用互斥锁exclusive lock的操作如ALTER TABLE。
> pg_dump只转储一个数据库。要备份集群中所有数据库通用的全局对象例如角色和表空间请使用 pg_dumpall。
转储可以是脚本或存档文件格式输出。脚本转储是纯文本文件其中包含将数据库重建到保存时所处状态所需的SQL命令。
pg_dump 把一个数据库转储为纯文本文件或者是其它格式,示例:
`pg_dump --dbname=postgresql://postgres:ohdsi@127.0.0.1:5432/OHDSI -t webapi.* > webapi.sql`
这将创建一个sql脚本但它并不是真正的sql脚本pg_dump生成的sql代码示例
```shell
COPY webapi.cohort_version (asset_id, comment, description, version, asset_json, archived, created_by_id, created_date) FROM stdin;
\.
--
-- Data for Name: concept_of_interest; Type: TABLE DATA; Schema: webapi; Owner: ohdsi_admin_user
--
COPY webapi.concept_of_interest (id, concept_id, concept_of_interest_id) FROM stdin;
1 4329847 4185932
2 4329847 77670
3 192671 4247120
4 192671 201340
```
当该脚本作为sql脚本运行时它会失败并显示以下错误。
- 用IDEA连接去执行sql文件时会报错
```shell
[57014] ERROR: COPY from stdin failed: COPY commands are only supported using the CopyManager API.
[11:21:06] 在位置COPY webapi.concept_of_interest, line 1
```
- 用pgAdmin 还原时,会报错:
```shell
pg_restore.exe --host "192.168.1.1" --port "5432" --username "postgres" --no-password --dbname "webapi" --verbose "D:\\backup\\webapi.sql"
pg_restore: 错误: 输入文件看起来像是文本格式的dump. 请使用psql.
```
当出现这种情况的时候,是因为用于还原转储的客户端工具无法处理来自(非标准)`COPY`命令的数据,这些数据被混合到脚本中。您需要`psql`才能恢复这样的转储。按照错误提示,使用`psql`
![image-20230626113256068](./images/image-20230626113256068.png)
输入完口令,就可以执行了。
`pg_dump `的其他参数如下:
```shell
D:\Program Files\PostgreSQL\13\bin>pg_dump --help
pg_dump 把一个数据库转储为纯文本文件或者是其它格式.
使用方法:
pg_dump [选项]... [数据库名字]
一般选项:
-f, --file=FILENAME 输出文件或目录名
-F, --format=c|d|t|p 输出文件格式 (定制, 目录, tar
明文 (默认值))
-j, --jobs=NUM 执行多个并行任务进行备份转储工作
-v, --verbose 详细模式
-V, --version 输出版本信息, 然后退出
-Z, --compress=0-9 被压缩格式的压缩级别
--lock-wait-timeout=TIMEOUT 在等待表锁超时后操作失败
--no-sync 不用等待变化安全写入磁盘
-?, --help 显示此帮助, 然后退出
控制输出内容选项:
-a, --data-only 只转储数据,不包括模式
-b, --blobs 在转储中包括大对象
-B, --no-blobs 排除转储中的大型对象
-c, --clean 在重新创建之前,先清除(删除)数据库对象
-C, --create 在转储中包括命令,以便创建数据库
-e, --extension=PATTERN 仅转储指定的扩展名
-E, --encoding=ENCODING 转储以ENCODING形式编码的数据
-n, --schema=PATTERN 只转储指定的模式
-N, --exclude-schema=PATTERN 不转储指定的模式
-O, --no-owner 在明文格式中, 忽略恢复对象所属者
-s, --schema-only 只转储模式, 不包括数据
-S, --superuser=NAME 在明文格式中使用指定的超级用户名
-t, --table=PATTERN 只转储指定的表
-T, --exclude-table=PATTERN 不转储指定的表
-x, --no-privileges 不要转储权限 (grant/revoke)
--binary-upgrade 只能由升级工具使用
--column-inserts 以带有列名的INSERT命令形式转储数据
--disable-dollar-quoting 取消美元 (符号) 引号, 使用 SQL 标准引号
--disable-triggers 在只恢复数据的过程中禁用触发器
--enable-row-security 启用行安全性(只转储用户能够访问的内容)
--exclude-table-data=PATTERN 不转储指定的表中的数据
--extra-float-digits=NUM 覆盖extra_float_digits的默认设置
--if-exists 当删除对象时使用IF EXISTS
--include-foreign-data=PATTERN
包含外部服务器上与模式匹配的
外部表的数据
--inserts 以INSERT命令而不是COPY命令的形式转储数据
--load-via-partition-root 通过根表加载分区
--no-comments 不转储注释
--no-publications 不转储发布
--no-security-labels 不转储安全标签的分配
--no-subscriptions 不转储订阅
--no-table-access-method do not dump table access methods
--no-tablespaces 不转储表空间分配信息
--no-toast-compression 不转储TOAST压缩方法
--no-unlogged-table-data 不转储没有日志的表数据
--on-conflict-do-nothing 将ON CONFLICT DO NOTHING添加到INSERT命令
--quote-all-identifiers 所有标识符加引号,即使不是关键字
--rows-per-insert=NROWS 每个插入的行数;意味着--inserts
--section=SECTION 备份命名的节 (数据前, 数据, 及 数据后)
--serializable-deferrable 等到备份可以无异常运行
--snapshot=SNAPSHOT 为转储使用给定的快照
--strict-names 要求每个表和()schema包括模式以匹配至少一个实体
--use-set-session-authorization
使用 SESSION AUTHORIZATION 命令代替
ALTER OWNER 命令来设置所有权
联接选项:
-d, --dbname=DBNAME 对数据库 DBNAME备份
-h, --host=主机名 数据库服务器的主机名或套接字目录
-p, --port=端口号 数据库服务器的端口号
-U, --username=名字 以指定的数据库用户联接
-w, --no-password 永远不提示输入口令
-W, --password 强制口令提示 (自动)
--role=ROLENAME 在转储前运行SET ROLE
如果没有提供数据库名字, 那么使用 PGDATABASE 环境变量的数值.
```
根据上面的命令参数,可以看到,`--inserts`这个参数可以替换掉`copy`命令,所以有另一种解决方案:
```shell
pg_dump --inserts --dbname=postgresql://postgres:ohdsi@127.0.0.1:5432/OHDSI -t webapi.* > webapi.sql
```
实例:
```shell
pg_dump -h 127.0.0.1 -p 5432 -U magicsat -f ./test/coastline.sql coastline
```
```sql
pg_dump -U magicsat -d coastline -h 127.0.0.1 >./test/coastline222.sql
```
```sql
pg_dump.exe -d "rural_house_330000" -h "192.168.4.199" -p "5432" -U "postgres" --no-password --inserts -W "ag123456" --table "risk_census_house_330100_jffx" -f D:\augurit\backup\jffx.sql
pg_dump. --inserts --dbname=postgresql://postgres:rural_house_330000@192.168.4.199:5432/rural_house_330000 -t "risk_census_house_330100_jffx" >D:\augurit\backup\jffx.sql
```
**可能遇到的问题:**
`pg_dump`命令需要输入密码才能执行。若想无需密码导数据有以下两种解决方法:
方法一设置pg环境变量
```she
export PGPASSWORD=''
```
方法二在pg_hba.conf中添加用户访问认证trust
```shell
# TYPE DATABASE USER ADDRESS METHOD
# IPv4 local connections:
host all all 127.0.0.1/32 md5
```
- TYPE连接方式'local'unix-domain的socket连接、`host` (TCP/IP socket)、`hostssl`(SSL加密的TCP/IP socket)
- DATABASE数据库名称'all' ,'sameuser','samerole','replication',`数据库名称` ,或者多个数据库名称用 `逗号`注意ALL不匹配 replication
- USER用户名称`all`,`一个用户名``一组用户名` ,多个用户时,可以用 `,`逗号隔开
- ADDRESS该参数可以为 `主机名称` 或者`IP/32(IPV4) `或 `IP/128(IPV6)`,主机名称以 `.`开头,`samehost`或`samenet` 匹配任意Ip地址
- METHOD该值可以为"trust", "reject", "md5", "password", "scram-sha-256","gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert"
> trust:无条件地允许联接。建议测试用
>
> reject:联接无条件拒绝。从一个组中"过滤"某些主机。
>
> md5:密码认证方式。密码是以md5形式传送给数据库
>
> password要求客户端提供一个未加密的口令进行认证。
>
> ident是Linux下PostgreSQL默认的local认证方式
例子表示允许 ip为127.0.0.1的所有用户通过md5加密的密码方式连接主机上的所有数据库
```shell
0,8,16,24,32 即表示掩码bit的个数
32 -> 192.168.1.1/32 表示必须是来自这个IP地址的访问才合法
24 -> 192.168.1.0/24 表示只要来自192.168.1.0 ~ 192.168.1.255的都合法;
16 -> 192.168.0.0/16 表示只要来自192.168.0.0 ~ 192.168.255.255的都合法;
8 -> 192.0.0.0/8 表示只要来自192.0.0.0 ~ 192.255.255.255的都合法;
```
### 3.还原pg_restore
pg_restore — 从pg_dump创建的档案文件中恢复PostgreSQL数据库是一种实用程序用于以非明文格式之一的[pg_dump](https://www.postgresql.org/docs/12/app-pgdump.html)创建的存档文件中恢复PostgreSQL数据库
语法:
```sql
pg_restore[ connection-option...] [ option...] [ filename]
```
一般选项:
```javascript
-d, --dbname=名字 连接数据库名字
-f, --file=文件名 输出文件名
-F, --format=c|d|t 备份文件格式(应该自动进行)
-l, --list 打印归档文件的 TOC 概述
-v, --verbose 详细模式
-V, --version 输出版本信息, 然后退出
-?, --help 显示此帮助, 然后退出
```
恢复控制选项:
```javascript
-a, --data-only 只恢复数据, 不包括模式
-c, --clean 在重新创建之前先清除删除数据库对象
-C, --create 创建目标数据库
-e, --exit-on-error 发生错误退出, 默认为继续
-I, --index=NAME 恢复指定名称的索引
-j, --jobs=NUM 执行多个并行任务进行恢复工作
-L, --use-list=FILENAME 从这个文件中使用指定的内容表排序输出
-n, --schema=NAME 在这个模式中只恢复对象
-O, --no-owner 不恢复对象所属者
-P, --function=NAME(args) 恢复指定名字的函数
-s, --schema-only 只恢复模式, 不包括数据
-S, --superuser=NAME 使用指定的超级用户来禁用触发器
-t, --table=NAME 恢复命名表
-T, --trigger=NAME 恢复指定名字的触发器
-x, --no-privileges 跳过处理权限的恢复 (grant/revoke)
-1, --single-transaction 作为单个事务恢复
--disable-triggers 在只恢复数据的过程中禁用触发器
--enable-row-security 启用行安全性
--if-exists 当删除对象时使用IF EXISTS
--no-data-for-failed-tables 对那些无法创建的表不进行数据恢复
--no-security-labels 不恢复安全标签信息
--no-tablespaces 不恢复表空间的分配信息
--section=SECTION 恢复命名节 (数据前数据及数据后)
--use-set-session-authorization 使用 SESSION AUTHORIZATION 命令代替ALTER OWNER 命令来设置所有权
```
联接选项:
```javascript
-h, --host=主机名 数据库服务器的主机名或套接字目录
-p, --port=端口号 数据库服务器的端口号
-U, --username=名字 以指定的数据库用户联接
-w, --no-password 永远不提示输入口令
-W, --password 强制口令提示 (自动)
--role=ROLENAME 在恢复前执行SET ROLE操作
```
选项 -I, -n, -P, -t, -T, 以及 --section 可以组合使用和指定
多次用于选择多个对象.
实例:
```shell
#切换到D:\Program Files\PostgreSQL\13\bin\
pg_restore --host "192.168.1.1" --port "5432" --username "postgres" --no-password --dbname "webapi" --verbose "D:\\backup\\webapi.sql"
```
> 注意纯文本格式的脚本pg_restore 是无法恢复的
### 4. docker环境
思路:
- 创建容器时将data目录挂载出来
- 进入容器,`pg_dump` 命令进行备份导出到挂载的目录下面这样在宿主机上就可以直接获取sql文件了
- 备份也是通过挂载的目录进行将SQL文件拷贝到挂载的目录下面进入容器内部执行`pg_restore`命令。
如果pg的数据目录没有挂载出来可以用`docker cp [source] [target]`命令将备份文件拷贝出来或获取备份文件。
### 参考文章
[1] https://www.jianshu.com/p/74063898e9ff
[2] https://blog.csdn.net/u011365831/article/details/79497596
[3] https://www.5axxw.com/questions/content/u5jus5