You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL15逻辑复制如何为订阅端额外列配置自定义赋值表达式

问题结论

PostgreSQL 15 原生逻辑复制不支持直接在订阅端为源端不存在的额外列配置自定义赋值表达式。默认逻辑下,源端发布未包含的列,同步写入时只会直接使用目标端对应列的DEFAULT值,若列非空且无默认值则直接报错,没有开放自定义赋值规则的配置入口。

多源同步区分tenant值的实现方案

根据你是否需要同步update/delete操作,可选两种成熟方案:

方案1:目标端复本触发器(仅需同步INSERT场景可用)

如果你的场景只需要同步源端的新增数据,不需要同步修改、删除操作,直接在目标端创建复本触发器即可实现不同来源数据赋值不同tenant值,不需要修改源端任何配置。
实现逻辑:

  • 创建不同订阅时,通过application_name参数标记数据源来源
  • 在目标表上创建仅在逻辑复制apply时生效的复本触发器,根据当前连接的application_name给tenant列赋值

操作示例:

  • 分别创建两个源库的订阅,标记连接名:
-- 订阅test1库
CREATE SUBSCRIPTION sb_test1 
CONNECTION 'dbname=test1 host=localhost port=5433 user=postgres password=你的密码' 
PUBLICATION pb_test 
WITH (slot_name = test_slot_v1, create_slot = false, application_name = 'repl_from_test1');

-- 订阅test2库
CREATE SUBSCRIPTION sb_test2 
CONNECTION 'dbname=test2 host=localhost port=5433 user=postgres password=你的密码' 
PUBLICATION pb_test 
WITH (slot_name = test_slot_v2, create_slot = false, application_name = 'repl_from_test2');
  • 在目标库创建触发器函数,根据连接来源赋值:
CREATE OR REPLACE FUNCTION set_tenant_for_repl()
RETURNS TRIGGER AS $$
BEGIN
  IF current_setting('application_name') = 'repl_from_test1' THEN
    NEW.tenant := 1;
  ELSIF current_setting('application_name') = 'repl_from_test2' THEN
    NEW.tenant := 2;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql STABLE;
  • 创建复本触发器(普通触发器默认不会被逻辑复制进程触发,必须加ENABLE REPLICA):
CREATE TRIGGER trg_set_tenant_repl
BEFORE INSERT ON test
FOR EACH ROW
ENABLE REPLICA
EXECUTE FUNCTION set_tenant_for_repl();

注意:该方案无法支持update/delete同步。因为目标端主键为(tenant,id),而源端同步的update/delete事件仅携带id值,没有tenant标识,apply时无法定位到对应租户下的行,会出现匹配不到记录的问题。

方案2:源端加固定值生成列(支持全操作同步,生产推荐)

如果需要同步insert/update/delete全类型操作,最稳妥的方案是在源端表上增加一个固定值的存储生成列,发布时把该列加入发布列表,同步到目标端时自带tenant标识,不需要目标端做额外逻辑处理,也不会影响原有业务。
操作示例:

  • 在test1库的test表上加生成列,固定值为1:
ALTER TABLE test ADD COLUMN tenant int GENERATED ALWAYS AS (1) STORED;
  • 在test2库的test表上加生成列,固定值为2:
ALTER TABLE test ADD COLUMN tenant int GENERATED ALWAYS AS (2) STORED;
  • 修改两个源库的发布,把tenant列加入发布字段列表:
-- 两个源库都执行
DROP PUBLICATION pb_test;
CREATE PUBLICATION pb_test FOR TABLE test (id, name, tenant);

该方案下,同步到目标端的每条记录都自带正确的tenant值,不管是新增、修改还是删除操作,都能通过(tenant,id)主键精准定位到对应行,同步逻辑稳定无额外兼容问题。加生成列的操作对业务完全透明:业务写入不需要指定tenant列,数据库会自动填充固定值,不会侵入现有业务逻辑。

提示:如果源端test表数据量极大,加stored生成列会触发表重写,建议在业务低峰期操作,或使用pg_repack等在线改表工具减少锁影响。


内容的提问来源于stack exchange,提问作者Stavros Koureas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 21:33:24