PostgreSQL 安装配置

以下简称 PgSQL

PGSql原生支持 NoSQL 的特性, 不过却是关系型数据库; 其JSON的性能不输给 MongoDB, 算是现在值得在生产环境之中投入使用的数据库.

安装配置

这里可以参考官方文档配置: 官方文档

直接选择对应系统配置源:

这里直接配置 Debian11 的源( postgresql-12, 默认很多发行版已经内置, 所以大部分情况不需要执行这些操作):

1
2
3
4
5
# Create the file repository configuration:
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# Import the repository signing key:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

此时源配置已经完成, 就可以准备安装服务:

1
2
3
4
5
6
# Update the package lists:
sudo apt-get update

# Install the latest version of PostgreSQL.
# If you want a specific version, use 'postgresql-12' or similar instead of 'postgresql':
sudo apt-get -y install postgresql postgresql-client

服务会自动配置到系统之中, 直接采用系统去调取服务:

1
2
3
4
sudo systemctl status postgresql.service # 查看系统管理状态
sudo systemctl start postgresql.service # 启用 PgSql 服务
sudo netstat -tulpn|grep -E 'postgresql|5432' # 查看系统是否启用了 postgresql 的 5432 端口服务
sudo systemctl enable postgresql.service # 设置开机自动启用 PgSql 服务

注意默认监听端口为 5432

账号配置

这里一般配置文件设置, 配置文件放置于 /etc/postgresql/14/main/postgresql.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13

# 文件默认的存放数据数据目录
data_directory = '/var/lib/postgresql/14/main' # use data in another directory

# host访问限制配置文件, 用于开放对面访问的 host 配置
hba_file = '/etc/postgresql/14/main/pg_hba.conf' # host-based authentication file

# 开放公网/局域网/本地地址
# 'localhost' 为默认的配置, 用于本地访问; '*' 则为对外全开放, 直接局域网 '192.168.1.x' 之类
listen_addresses = '*' # what IP address(es) to listen on;

# 默认访问的端口号
port = 5432 # (change requires restart)

这里基本上只需要最基础的这三个配置, 首先是创建对外账号处理( 修改配置之后重启服务 ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-- 这里必须要切换到 `postgres` 这个超级用户才能进行客户端管理:
-- sudo -i -u postgres
-- 之后切换完成在命令行输入
-- psql
-- 后续输入以下指令创建账号

-- 创建个 `manager` 的账号, 密码为 `qwerty123456`
CREATE ROLE manager WITH
LOGIN
SUPERUSER
CREATEDB
CREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1
PASSWORD 'qwerty123456';
COMMENT ON ROLE manager IS '自定义对外数据库管理账号';
-- 这里需要说明 WITH 之后每个参数所代表的意义(生产环境中应谨慎分配 SUPERUSER 此权限)
-- LOGIN : 指定该角色可以登录数据库, 相当于创建了一个数据库用户. 没有 LOGIN 属性的角色只能作为权限组使用, 无法直接连接数据库
-- SUPERUSER : 赋予该角色超级用户权限. 拥有此属性的角色可以绕过数据库的所有权限检查(除了 LOGIN 权限限制), 能执行所有操作(如创建 / 删除数据库、修改系统配置、管理所有角色等)
-- CREATEDB : 允许该角色创建新的数据库. 没有此权限的角色无法执行 CREATE DATABASE 语句
-- CREATEROLE : 允许该角色创建、修改、删除其他数据库角色. 拥有此权限的角色可以管理其他角色的属性(如权限、密码等), 但需要注意:普通的 CREATEROLE 角色无法创建超级用户, 除非自身也是超级用户
-- INHERIT : 指定该角色可以继承其所属角色的权限. 如果这个 manager 角色被加入其他角色组, 那么 manager 会自动拥有该角色组的所有权限. 这是 PostgreSQL 角色的默认属性, 与之相对的是 NOINHERIT(不继承权限)
-- NOREPLICATION : 指定该角色不是复制角色. 复制角色(REPLICATION 属性)用于流复制场景, 通常是备库连接主库时使用的角色. NOREPLICATION 表示此角色不能用于复制操作
-- CONNECTION LIMIT -1 : 设置该角色的最大并发连接数限制. -1 表示无限制, 即该角色可以同时建立任意数量的数据库连接.如果设置为正数(如 10), 则最多只能有 10 个并发连接
-- PASSWORD 'qwerty123456': 设置该角色的登录密码为 qwerty123456. 密码会被加密后存储在系统表中, 用于客户端登录时的身份验证
-- COMMENT ON ROLE 账户名 IS '详情': 给角色添加注释, 方便管理员理解该角色的用途


-- 如果不满意的话可以删除账号
DROP ROLE manager;


-- 构建简单的底权限账户, 假设创建个 api 角色指定只能处理 sdk 库, 这类账号不允许设置超级权限
CREATE ROLE api WITH
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1
PASSWORD 'qwerty123456';
COMMENT ON ROLE api IS '仅用于操作 sdk 数据库的低权限账号';
-- NOSUPERUSER -- 明确无超级权限,生产环境必须
-- NOCREATEDB -- 禁止创建数据库
-- NOCREATEROLE -- 禁止管理其他角色
-- 建议生产环境使用强密码

---- -----------------------------------
---- 注意: 以下需要用高权限登陆处理
---- -----------------------------------

-- 授予连接 sdk 数据库的权限
GRANT CONNECT ON DATABASE sdk TO api;

-- 切换到 sdk 数据库执行(否则无法授予模式权限)
\c sdk

-- 授予对 public 模式的使用权限
GRANT USAGE ON SCHEMA public TO sdk;

-- 授予对 public 模式下所有表增删改查的权限
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO sdk;

-- 自动授予未来新增表的权限(避免后续建表重复授权)
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO sdk;

之后测试下登录:

1
2
3
# 输入以下指令之后确认密码查看是否允许登录
# postgres 为系统默认数据库, 确认登录没问题就代表账号创建完成
psql --host=127.0.0.1 --username=manager --dbname=postgres

这里需要手动写入 Host 表来开放访问( Host 文件: /etc/postgresql/14/main/pg_hba.conf ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 访问HOST	访问数据库	访问用户	  	  访问地址	  			  加密方式		
# TYPE DATABASE USER ADDRESS METHOD
# 这里不需修改其他, 追加创建的用户即可, 加密方式最低采用md5
host all manager 0.0.0.0/0 md5
# TYPE - host: 表示通过 TCP/IP 网络连接(区别于本地 unix socket 的 local 类型)
# DATABASE - all: 允许该用户访问所有数据库, 如果想指定多个数据库以逗号分割(db1,db2,db3)
# 可以 '@文件名' 加载, 例如 /etc/postgresql/14/main/db_list.conf 添加文件, 每一行写一个数据库名称
# 然后追加 @/etc/postgresql/14/main/db_list.conf 来指定读取文件加载数据库
# USER - manager: 匹配要授权的数据库角色
# ADDRESS - 0.0.0.0/0: 允许所有 IP 地址的客户端连接(生产环境需谨慎,建议限定具体 IP / 网段), 支持网段配置
# /32 = 子网掩码 255.255.255.255 → 单个 IP - 常用
# /24 = 子网掩码 255.255.255.0 → 256 个 IP - 常用
# /16 = 子网掩码 255.255.0.0 → 65536 个 IP
# 这里提供几个常用的网段地址:
# 127.0.0.1/32 - 仅允许本地主机连接
# 192.168.1.0/24 - 允许 192.168.1.1 ~ 192.168.1.255 网段的客户端连接
# 10.0.0.0/8 - 允许所有 10.x.x.x 网段的客户端连接
# 172.16.0.0/12 - 允许 172.16.0.1 ~ 172.31.255.255 网段的客户端连接
# 192.168.0.0/16 - 允许所有 192.168.x.x 网段的客户端连接
# 10.1.2.3/32 仅允许 单个 IP 10.1.2.3 连接
# METHOD - md5: 加密方案, 采用 md5 加密兼容性比较好, 但是官方比较推荐的 scram-sha-256 方式, 可以按需来选择

配置好之后重启服务即可, 这样就能直接访问了.

常用语句

实际上 PSQL 和其他 MySQL/MariaDB 语法类型, 所以学习起来也很容易:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
-- 查询数据库列表, 以下语句都是查询数据库列表
\l
SELECT datname
FROM pg_database;

-- 创建数据库指定编码
CREATE DATABASE sdk
WITH
ENCODING = 'UTF8';
-- PSQL 不需要处理类似 mysql 的 utf8/utf8mb3/utf8mb4 差别, 这是 mysql 之类的设计缺陷

-- 切换数据库
\c sdk

-- 创建表设置 id 为主键并设置自增长
-- SERIAL 对应 MYSQL 的 integer 类型(范围 -2147483648 ~ 2147483647)
-- BIGSERIAL 对应 MYSQL 的 bigint 类型, 范围更大
CREATE TABLE sdk_user_info
(
id BIGSERIAL NOT NULL PRIMARY KEY,
username VARCHAR(64) NOT NULL,
email VARCHAR(255) NOT NULL DEFAULT ''
);

-- 给字段加注释, PSQL 和 MySQL 标识注释差别很大, 必须字符串采用单引号(字符串采用双引号可能会异常)
COMMENT ON COLUMN sdk_user_info.id IS '用户唯一标识,自增主键';
COMMENT ON COLUMN sdk_user_info.username IS '用户登录名';
COMMENT ON COLUMN sdk_user_info.email IS '邮箱地址';

-- 给表加注释
COMMENT ON TABLE sdk_user_info IS '测试用户表';

-- 查看建表详情
\d+ sdk_user_info

-- 插入单条数据(自增主键 id 可省略)
INSERT INTO sdk_user_info(username, email)
VALUES ('meteorcat', '[email protected]');

-- 查询所有字段、所有数据
SELECT *
FROM sdk_user_info;

-- 查询指定字段 + 条件过滤
SELECT username, email
FROM sdk_user_info
WHERE id > 1;

-- 排序 + 分页(PostgreSQL 推荐用 LIMIT + OFFSET)
SELECT *
FROM sdk_user_info
ORDER BY id DESC
LIMIT 10 OFFSET 0;
-- 取前10条

-- 去重查询
SELECT DISTINCT username
FROM sdk_user_info;

-- 聚合查询(统计总数)
SELECT COUNT(*) AS user_count
FROM sdk_user_info;

-- 修改单条数据(必须加 WHERE,否则修改全表!)
UPDATE sdk_user_info
SET email = '[email protected]'
WHERE id = 1;

-- 删除单条数据
DELETE
FROM sdk_user_info
WHERE id = 100;

PostgreSQL 的增删改查(CRUD)语法和 MySQL 大部分一致, 所以很好直接切换过来.

导出备份

PostgreSQL 官方提供的 pg_dump(单库/表导出)pg_dumpall(全实例导出) 是首选工具, 支持自定义导出格式、压缩及增量逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 全量导出, 基础命令(明文 SQL 格式,便于直接恢复)
# 导出 PostgreSQL 实例下所有数据库(含系统库 postgres、template0 等), 及角色和表空间等全局对象
pg_dumpall -U manager -h 127.0.0.1 -p 5432 > /backup/pgsql_full_$(date +%Y%m%d).sql
# -U: 指定导出账号(需有 SELECT ANY TABLE 权限)
# -h/-p: 数据库地址和端口(远程导出需配置 pg_hba.conf 允许访问)


# 指定数据库导出, 导出为可直接执行的 SQL 脚本(推荐日常备份, 假设数据库为 app_db)
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -F p -f /backup/pgsql_appdb_$(date +%Y%m%d).sql
# -F p: 明文 SQL 格式(可直接用 psql 恢复,可读性强)
# -F c: 自定义二进制格式(压缩率更高, 支持按表 /schema 恢复,适合大库)


# 仅导出 app_db 数据库结构(无数据,适合新建环境)
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -F p -s -f /backup/pgsql_appdb_schema_$(date +%Y%m%d).sql


# 指定数据库单表导出, 含结构+数据(假设是 app_db 数据库下的 user_info 表)
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -t public.user_info -f /backup/pgsql_userinfo_$(date +%Y%m%d).sql
# -s(--schema-only):仅导出结构(表、索引、函数等)
# -a(--data-only): 仅导出数据(INSERT 语句)


# 仅导出 user_info 表数据(无结构,适合数据补录)
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -t public.user_info -a -f /backup/pgsql_userinfo_data_$(date +%Y%m%d).sql


# 指定数据库多表导出, 用 -t 多次指定
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -t public.user_info -t public.order_detail -f /backup/pgsql_user_order_$(date +%Y%m%d).sql


# 指定数据库单表的查询数据导出成 CSV, 便于直接 Excel 打开(假设是 app_db 数据库下的 order_detail 表之中创建时间大于 2025-01-01 00:00:00 的数据)
psql -U manager -h 127.0.0.1 -p 5432 -d app_db -c "COPY (SELECT * FROM public.order_detail WHERE create_time >= '2025-01-01 00:00:00') TO '/backup/pgsql_order_202501.csv' WITH (FORMAT csv, HEADER, DELIMITER ',');"


# 导出为 SQL 脚本数据(含插入语句)
pg_dump -U manager -h 127.0.0.1 -p 5432 -d app_db -t public.order_detail --where "create_time >= '2025-01-01 00:00:00'" -f /backup/pgsql_order_202501.sql

这些命令直接运行定时脚本即可, 需要注意的是必须构建个本地免密登陆的 PSQL 账号来方便直接导出(绝对不要对公网暴露).

不过 PSQL 有系统机制来采用免密登陆操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 在执行备份脚本的用户(如 root 或专用备份用户 backup)家目录下创建文件
# 注意该系统用户需要指定不允许登陆: sudo useradd -m -s /sbin/nologin backup
sudo -i -u backup # 切换到专门备份用户
vim ~/.pgpass # 生成|编辑免密配置文件

# 写入内容
echo "127.0.0.1:5432:*:manager:你的密码" > ~/.pgpass
# * 表示匹配所有数据库,也可指定具体库(如 app_db)

# 设置权限
chmod 600 ~/.pgpass

# 验证免密登录(无密码提示即成功)
psql -U manager -h 127.0.0.1 -d postgres -c "SELECT version();"

# 再次账户指定定时脚本来导出
crontab -e # 启动编辑定时脚本