
PostgreSQL 中的 PARALLEL SAFE 是一个函数属性声明,用于明确告知查询规划器:该函数在并行执行上下文中是安全的,可以被下推到并行工作进程(worker)中执行。它不是“开启并行”的开关,而是“允许并行”的前提条件之一。
PARALLEL SAFE 的作用与意义
当 PostgreSQL 启动并行查询(如并行顺序扫描、并行聚合等)时,规划器会检查涉及的函数是否标记为 PARALLEL SAFE。若函数未声明或声明为 PARALLEL RESTRICTED / PARALLEL UNSAFE,则整个并行计划可能被降级为串行执行,或相关计算被迫保留在主进程(leader)中完成,削弱并行收益。
注意:PARALLEL SAFE 不代表函数一定会被并行调用,它只是移除了并行执行的障碍;是否真正并行,还取决于查询结构、成本估算、max_parallel_workers_per_gather 设置及系统资源等。
三种并行兼容性级别对比
PostgreSQL 定义了三个函数并行安全性级别,必须显式指定(默认为 PARALLEL RESTRICTED):
-
PARALLEL SAFE:函数不访问共享状态(如序列、临时表、客户端连接信息)、不修改数据库、不依赖会话级变量(如
current_user、session_user)、不调用非 SAFE 函数。可安全地在任意 worker 进程中多次执行。 -
PARALLEL RESTRICTED:函数可在 leader 进程中执行,但不能下推至 worker(例如依赖
pg_backend_pid()、clock_timestamp()或写入临时表)。这是用户自定义函数的默认级别。 -
PARALLEL UNSAFE:函数存在明显副作用或状态依赖(如修改全局变量、调用
dblink、执行 DML),禁止在并行上下文中调用,否则可能导致错误或数据不一致。
如何正确声明 PARALLEL SAFE
在创建函数时,通过 PARALLEL 子句显式指定:
RETURNS int AS $$ SELECT a + b; $$
LANGUAGE SQL
PARALLEL SAFE;
关键注意事项:
- 所有被该函数直接或间接调用的其他函数,也必须是 PARALLEL SAFE,否则声明无效,建表时会报错。
- 函数体中不可出现:
NEXTVAL/CURRVAL(序列)、txid_current()、pg_snapshot_xmin()、set_config()、对临时表的读写、PL/pgSQL 的GET DIAGNOSTICS等。 - 纯计算类函数(如字符串处理、数学运算、JSON 解析)通常天然适合标记为 PARALLEL SAFE;含 I/O、状态变更、事务/会话依赖的操作需谨慎评估。
验证与调试技巧
可通过系统视图确认函数的并行属性:
SELECT proname, proparallelFROM pg_proc
WHERE proname = 'my_add';
返回值含义:s=SAFE,r=RESTRICTED,u=UNSAFE。
启用并行查询后,使用 EXPLAIN (ANALYZE, VERBOSE) 查看执行计划,观察函数调用是否出现在 Gather 节点之下(即由 worker 执行),是判断其是否真正并行化的直接依据。










