Electric 同步引擎的 PostgreSQL 权限配置全指南:三种模式、核心权限清单与手动发布配置
2026/9/17 19:15:32 网站建设 项目流程

Electric 同步引擎的 PostgreSQL 权限配置全指南:三种模式、核心权限清单与手动发布配置

【免费下载链接】electricThe agent platform built on sync.项目地址: https://gitcode.com/GitHub_Trending/el/electric

本指南基于开源仓库electric(Agent 平台的内置同步引擎,核心实现位于 packages/sync-service)官方文档与源码,系统讲解如何为 Electric 创建和配置具备必要权限的 PostgreSQL 用户。读完本文,你将掌握超级用户、Electric 托管发布(自动模式)与手动模式(最小权限)三种权限方案的适用场景与完整 SQL 配置,理解ELECTRIC_MANUAL_TABLE_PUBLISHINGELECTRIC_REPLICATION_STREAM_ID等关键配置项背后的源码实现,并能够独立完成发布(Publication)与REPLICA IDENTITY FULL的手动配置与验证。

你应该选择哪种权限方案?

Electric 需要通过 逻辑复制 读取 Postgres 的变更流,并管理发布对象(Publication)。根据不同场景,官方文档给出了三种由高到低的权限方案:

方案适用场景优点缺点连接配置
🟢 超级用户(推荐用于开发)本地开发、测试或简单的生产部署设置最简单,Electric 全自动管理一切权限级别最高DATABASE_URL=postgresql://postgres:...
🔵 Electric 托管发布(自动模式,生产推荐)生产环境,Electric 可以拥有数据库表Electric 自动管理发布与REPLICA IDENTITYElectric 必须拥有表(应用失去表所有权)创建专用用户并转移表所有权
🔴 手动模式(最小权限)高安全环境、应用必须拥有表、严格权限分离应用保留表所有权,Electric 权限最小DBA 必须预配置发布,新增表需手动加入REPLICATION+SELECT,DBA 配置发布

三种方案的详细配置步骤分别见下文 开发环境配置、Electric 托管发布配置 与 手动模式配置。

自动 vs 手动发布管理

Electric 在两种模式下运行,其行为差异由配置项ELECTRIC_MANUAL_TABLE_PUBLISHING控制(默认值为false)。

1. Electric 托管发布(自动模式,推荐)

当客户端请求某个表的 shape 时,Electric 会在 Postgres 内自动创建发布(publication)并把表加入其中,同时自动设置REPLICA IDENTITY FULL。这要求 Electric 的数据库用户具备数据库上的CREATE权限表的所有权——PostgreSQL 规定:只有表的所有者才能把表加入发布,也只有表的所有者才能设置REPLICA IDENTITY FULL

从源码看,该逻辑由 configurator.ex 中的PublicationManager.Configurator(一个 GenServer)实现。它维护一个"目标关系集合",收到 shape 订阅请求后去比对当前发布的实际状态,并生成to_add(加入发布)、to_configure_replica_identity(配置 replica identity)、to_drop(移除)等动作清单,最终通过 configuration.ex 中的configure_table_for_replication/4在一个事务内依次执行ALTER PUBLICATION ... ADD TABLEALTER TABLE ... REPLICA IDENTITY FULL

defp do_publication_update(:add_and_configure, filter, state) do with :ok <- Configuration.configure_table_for_replication( state.db_pool, state.publication_name, filter ) do {:ok, :configured} end end

值得注意的实现细节:源码注释明确指出,ALTER PUBLICATION ... ADD TABLE只持有表的SHARE UPDATE EXCLUSIVE锁,与写入者不冲突,因此在该事务内还会额外执行LOCK TABLE ... IN SHARE MODE作为屏障,等待所有在途写入者结束,从而保证"加入发布之前的写入要么通过初始快照可见、要么通过复制流可见",不会出现变更丢失。详见 configuration.ex。

2. 手动模式

手动模式下,发布由 DBA 提前创建和维护,Electric 只负责校验现有配置是否满足要求,而不会自动增删表。启用方式:

ELECTRIC_MANUAL_TABLE_PUBLISHING=true

该模式只需要REPLICATIONSELECT权限,但你必须在请求 shape 之前,预先创建发布、把表加入发布,并为每张表设置REPLICA IDENTITY FULL

从源码看,configurator.ex 中的can_update_publication?/1函数同时检查"能否修改发布"和"是否手动模式"两个条件:

defp can_update_publication?(%__MODULE__{ can_alter_publication?: can_alter, manual_table_publishing?: manual }) do can_alter and not manual end

当手动模式开启时,Electric 对缺失的配置会返回明确的错误而不是自行修复。例如表未加入发布时,configurator.ex 会生成如下错误信息:

Database table "public.items" is missing from the publication "..." and the ELECTRIC_MANUAL_TABLE_PUBLISHING setting prevents Electric from adding it

这一行为有完整的测试与集成测试覆盖:单元测试见 publication_manager_manual_test.exs(分别验证"表不在发布中报错"与"replica identity 非 FULL 报错"两个场景);端到端集成测试见 manual-table-publishing.lux,它用一个low_privilege角色实际启动 Postgres 与 Electric,逐级演示了"缺表 → 加表 → 仍缺 replica identity → 设置 FULL → 缺 SELECT 权限"的完整报错链路。

核心权限要求一览

根据模式不同,Electric 所需的 PostgreSQL 权限如下:

权限用途Electric 托管手动模式
REPLICATION启用逻辑复制流✅ 必需✅ 必需
表上的SELECT读取表数据以生成初始 shape 快照✅ 必需✅ 必需
数据库上的CREATE创建发布✅ 必需❌ 不需要
表所有权设置REPLICA IDENTITY FULL并把表加入发布✅ 必需❌ 由 DBA 配置
发布所有权修改发布(增删表)✅ 必需❌ 由 DBA 配置

另外,DATABASE_URL中的用户必须具有REPLICATION角色。可参考 配置参考 中关于DATABASE_URL的说明:连接串的userspec部分指定的就是 Electric 连接 Postgres 所用的用户。

设置示例

开发环境配置(For Development)

开发环境直接使用默认的postgres超级用户(或其他超级用户角色):

DATABASE_URL=postgresql://postgres:your_password@localhost:5432/your_database

Electric 会自动创建发布、配置REPLICA IDENTITY FULL并管理一切。对于追求简便、安全性要求不高的简单生产部署,同样适用。

Electric 托管发布配置(Electric-managed publications Setup)

创建一个专用 Electric 用户,并授予自动表配置所需权限。Electric 会在 shape 被请求时自动创建发布、加入表:

-- 创建带 REPLICATION 的 Electric 用户 CREATE ROLE electric_user WITH LOGIN PASSWORD 'secure_password' REPLICATION; -- 授予数据库级权限 GRANT CONNECT ON DATABASE mydb TO electric_user; GRANT USAGE ON SCHEMA public TO electric_user; GRANT CREATE ON DATABASE mydb TO electric_user; -- 创建发布所需 -- 授予表上的 SELECT(Electric 只读,仅需读数据) -- 所有表: GRANT SELECT ON ALL TABLES IN SCHEMA public TO electric_user; -- 未来新建的表自动获得 SELECT(ALTER DEFAULT PRIVILEGES) ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO electric_user; -- 只授权特定表: -- GRANT SELECT ON public.users, public.posts TO electric_user;

将表所有权转移给 Electric:

PostgreSQL 要求表所有者才能把表加入发布并设置REPLICA IDENTITY FULL,因此必须把表所有权转移给electric_user

针对特定表(推荐做法):

ALTER TABLE public.users OWNER TO electric_user; ALTER TABLE public.posts OWNER TO electric_user; ALTER TABLE public.comments OWNER TO electric_user;

或者将该 schema 下的所有表一次转移:

DO $$ DECLARE r RECORD; BEGIN FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP EXECUTE 'ALTER TABLE public.' || quote_ident(r.tablename) || ' OWNER TO electric_user'; END LOOP; END$$;

[!Warning] 所有权转移警告 转移表所有权会让原所有者失去所有权。如果应用必须保留表所有权,请改用 手动模式,由 DBA 预先配置发布与REPLICA IDENTITY FULL

配置完成后连接 Electric:

DATABASE_URL=postgresql://electric_user:secure_password@localhost:5432/mydb

手动模式配置(Manual Mode Setup)

对于有严格安全要求的环境,可使用手动发布管理来最小化 Electric 的权限:

-- 创建带 REPLICATION(但其他权限最小化)的 Electric 用户 CREATE ROLE electric_user WITH LOGIN PASSWORD 'secure_password' REPLICATION; -- 只授予连接与 usage 权限 GRANT CONNECT ON DATABASE mydb TO electric_user; GRANT USAGE ON SCHEMA public TO electric_user; -- 只对特定表授予 SELECT GRANT SELECT ON public.users TO electric_user; GRANT SELECT ON public.posts TO electric_user;

然后以超级用户或数据库所有者身份,按照下文 手动配置步骤 创建发布、加入表并配置 replica identity。

配置 Electric:

DATABASE_URL=postgresql://electric_user:secure_password@localhost:5432/mydb ELECTRIC_MANUAL_TABLE_PUBLISHING=true

AWS RDS 和 Aurora

AWS RDS 与 Aurora 在复制权限方面需要特殊处理。参考 AWS 集成指南:

  1. 在自定义参数组中将rds.logical_replication=1(这会设置wal_level=logical),然后重启实例;
  2. 默认的postgres用户已具备REPLICATION角色;若需给其他用户授予复制权限,通过rds_replication角色实现:
GRANT rds_replication TO someuser;

手动配置步骤(Manual Configuration Steps)

当你需要为ELECTRIC_MANUAL_TABLE_PUBLISHING=true手动配置发布与 replica identity 时,按以下 5 步执行。

1. 创建发布(Create the Publication)

-- 创建空发布 CREATE PUBLICATION electric_publication_default; -- 或使用自定义名称(需同时配置 ELECTRIC_REPLICATION_STREAM_ID 保持一致) CREATE PUBLICATION my_custom_publication;

发布名称默认形如electric_publication_<stream_id>。默认的ELECTRIC_REPLICATION_STREAM_IDdefault(见 config.ex 中的replication_stream_id: "default"),该配置项作为逻辑复制发布与 slot 名称的后缀,详见 配置参考。

2. 将表加入发布(Add Tables to the Publication)

ALTER PUBLICATION electric_publication_default ADD TABLE public.users; ALTER PUBLICATION electric_publication_default ADD TABLE public.posts; ALTER PUBLICATION electric_publication_default ADD TABLE public.comments;

[!Tip] 更精简的等价操作 配置参考 中给出了每次新增 shape 前的等价最小步骤,可将两步合并到同一事务:

BEGIN; ALTER PUBLICATION electric_publication_default ADD TABLE <my table>; ALTER TABLE <my table> REPLICA IDENTITY FULL; COMMIT;

3. 配置 Replica Identity

每张要同步的表都必须把 replica identity 设置为FULL

ALTER TABLE public.users REPLICA IDENTITY FULL; ALTER TABLE public.posts REPLICA IDENTITY FULL; ALTER TABLE public.comments REPLICA IDENTITY FULL;

这会让 Postgres 在复制流中输出所有列的值,是 Electric 实现精确变更跟踪的前提。

4. 设置发布所有权

让 Electric 用户成为发布的所有者(或确保发布由 Electric 连接所用的同一用户创建):

ALTER PUBLICATION electric_publication_default OWNER TO electric_user;

5. 验证配置

用下面的 SQL 检查发布是否配置正确:

-- 验证 Electric 角色具有 REPLICATION 权限 SELECT rolname, rolreplication FROM pg_roles WHERE rolname = 'electric_user'; -- 列出所有发布 SELECT * FROM pg_publication; -- 检查发布设置 SELECT pubname, pubinsert, pubupdate, pubdelete, pubtruncate FROM pg_publication WHERE pubname = 'electric_publication_default'; -- 列出发布中的表 SELECT schemaname, tablename FROM pg_publication_tables WHERE pubname = 'electric_publication_default'; -- 检查表的 replica identity SELECT schemaname, tablename, relreplident FROM pg_class JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid WHERE relreplident = 'f'; -- 'f' 表示 FULL

从源码看,Electric 启动时正是通过类似的 SQL 来"体检"发布状态的。configuration.ex 中的check_publication_status!/2会查询:

  • pg_get_userbyid(p.pubowner) = current_role—— 当前角色能否修改发布(can_alter_publication);
  • pubinsert AND pubupdate AND pubdelete AND pubtruncate—— 发布是否覆盖全部操作类型(publishes_all_operations);
  • PostgreSQL 18+ 上还会检查pubgencols是否发布生成列(publishes_generated_columns)。

如果发布不存在或未发布全部操作,configurator.ex 会判定为致命配置错误;在自动模式下会尝试重启连接子系统自愈,而在手动模式下则只记录警告,提示你手动修正配置。

常见权限错误排查

以下内容摘录自 故障排查指南 的 "Database permissions" 一节:

"insufficient privilege to create publication"

  • 原因:用户没有数据库上的CREATE权限。
  • 解决:执行GRANT CREATE ON DATABASE mydb TO electric_user;,或者改用手动发布管理(由超级用户创建发布并设置ELECTRIC_MANUAL_TABLE_PUBLISHING=true)。

"publication not owned by the provided user"

  • 原因:发布已存在,但所有者是其他用户。
  • 解决:转移发布所有权:
    ALTER PUBLICATION electric_publication_default OWNER TO electric_user;

"table does not have its replica identity set to FULL"

  • 原因:表未配置REPLICA IDENTITY FULL
  • 解决:手动设置:
    ALTER TABLE schema.tablename REPLICA IDENTITY FULL;

"permission denied for table"

  • 原因:Electric 用户没有该表的SELECT权限。
  • 解决:授权:
    GRANT SELECT ON schema.tablename TO electric_user;

"must be owner of table"

  • 原因:执行了需要所有权的操作(如ALTER TABLE ... REPLICA IDENTITY FULL或把表加入发布)。
  • 解决:以表所有者(或超级用户)身份执行,或转移所有权:
    ALTER TABLE schema.tablename OWNER TO electric_user;

从源码理解权限校验链路

最后,把上面提到的实现串成一条完整的调用链,便于你深入阅读源码:

  1. shape 订阅请求到达后,PublicationManager向 Configurator(Electric.Replication.PublicationManager.Configurator)发出更新请求;
  2. Configurator 通过 Configuration(Electric.Postgres.Configuration)执行check_publication_status!/2检查发布存在性与操作覆盖度,再执行determine_publication_relation_actions!/3计算需要的动作;
  3. can_update_publication?/1返回true(可修改发布且非手动模式),按排序后的动作清单依次执行add_table_to_publication/4set_table_replica_identity_full/4drop_table_from_publication/4;否则对每个缺失的表返回relation_missing_from_publicationmisconfigured_replica_identity错误;
  4. 上述校验逻辑由 publication_manager_manual_test.exs 与 manual-table-publishing.lux 双重验证。

下一步

  • 查看 部署指南 了解生产环境部署方案;
  • 阅读 安全最佳实践;
  • 遇到问题参考 故障排查指南;
  • 查看 配置参考 了解全部可用配置项(如DATABASE_URLELECTRIC_POOLED_DATABASE_URLELECTRIC_REPLICATION_STREAM_ID等)。

【免费下载链接】electricThe agent platform built on sync.项目地址: https://gitcode.com/GitHub_Trending/el/electric

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询