Files
Neo-ZQYY/docs/database/BD_Manual_fdw_reverse_retention_clue.md

11 KiB
Raw Blame History

BD 手册FDW 反向映射 — ETL 库读取业务库维客线索

创建日期2026-02-26member_birthday_manual2026-03-19 重写为当前版本 替代文档:docs/database/_archived/BD_Manual_fdw_reverse_member_birthday.md 关联 SQLdb/fdw/setup_fdw_reverse.sql(生产)、db/fdw/setup_fdw_reverse_test.sql(测试) 关联表文档:docs/database/BD_Manual_member_retention_clue.md


1. 概述

etl_feiqiu(生产)/ test_etl_feiqiu(测试)数据库中,通过 postgres_fdw 创建指向 zqyy_app / test_zqyy_app 的外部表 fdw_app.member_retention_clue,使 ETL DWS 任务可只读访问助教为会员记录的维客线索数据。

方向:etl_feiqiu → zqyy_app(与正向 FDW setup_fdw.sqlzqyy_app → etl_feiqiu 方向相反)。

数据流向

zqyy_app.public.member_retention_clue  (业务库源表,后端 API 写入)
        │
        │  postgres_fdw只读
        ▼
etl_feiqiu.fdw_app.member_retention_clue  ETL 库外部表DWS 任务读取)

历史沿革

日期 事件
2026-02-22 初版:fdw_app.member_birthday_manual(映射助教手动补录生日表)
2026-02-26 重构:member_birthday_manualmember_retention_clue(维客线索替代单一生日方案)
2026-02-27 业务库侧新增 source线索来源FDW 外部表定义未同步更新
2026-03-08 业务库侧 category 枚举对齐:客户基础信息客户基础

2. 变更说明

2.1 新增对象

所在库 对象类型 名称 说明
etl_feiqiu / test_etl_feiqiu 扩展 postgres_fdw PostgreSQL 外部数据包装器(如已安装则跳过)
etl_feiqiu 外部服务器 zqyy_app_server 指向 zqyy_app 业务库host/port 按环境配置)
test_etl_feiqiu 外部服务器 test_zqyy_app_server 指向 test_zqyy_app 测试业务库
etl_feiqiu / test_etl_feiqiu 用户映射 etl_user → app_reader ETL 连接角色映射到业务库只读角色
etl_feiqiu / test_etl_feiqiu Schema fdw_app 存放来自业务库的外部表
etl_feiqiu / test_etl_feiqiu 外部表 fdw_app.member_retention_clue 映射 public.member_retention_clue

2.2 外部表列定义

列名 类型 说明
id BIGINT 自增主键
member_id BIGINT 会员 ID
category VARCHAR(20) 线索大类6 值枚举:客户基础/消费习惯/玩法偏好/促销偏好/社交关系/重要反馈)
summary VARCHAR(200) 摘要
detail TEXT 详情
recorded_by_assistant_id BIGINT 记录助教 ID
recorded_by_name VARCHAR(50) 记录助教姓名
recorded_at TIMESTAMPTZ 记录时间
site_id BIGINT 门店 ID

注意:业务库侧 member_retention_clue 已于 2026-02-27 新增 source VARCHAR(20) 列(线索来源:manual / ai_consumption / ai_note),但当前 FDW 外部表定义(db/fdw/setup_fdw_reverse*.sql)尚未包含此列。如 ETL 任务需要读取 source 字段,需更新外部表定义并重新执行部署脚本。

2.3 角色与权限

角色 所在库 用途
etl_user etl_feiqiu / test_etl_feiqiu ETL 连接角色,通过 FDW 只读访问业务库数据
app_reader zqyy_app / test_zqyy_app 业务库只读角色,供 FDW 用户映射使用

权限配置:

角色 Schema 权限
etl_user fdw_app USAGE + SELECT ON ALL TABLES + ALTER DEFAULT PRIVILEGES(自动授权未来新增外部表)

3. 与正向 FDW 的对比

维度 正向 FDWsetup_fdw.sql 反向 FDWsetup_fdw_reverse.sql
执行位置 zqyy_app 业务库 etl_feiqiu ETL 库
数据方向 业务库读取 ETL 数据 ETL 库读取业务库数据
目标 Schema fdw_etl35 张外部表) fdw_app1 张外部表)
导入方式 IMPORT FOREIGN SCHEMA app(批量) CREATE FOREIGN TABLE(逐表定义)
消费方 后端 API ETL DWS 任务
文档 BD_Manual_fdw_etl_setup.md 本文档

4. 兼容性影响

组件 影响
ETL DWS 任务 可通过 fdw_app.member_retention_clue 只读访问维客线索数据。当前无 DWS 任务直接消费此表(原 member_birthday_manual 的生日读取逻辑已移除,生日仅从 dim_member.birthday 读取)
后端 API 无影响。后端直接写入 zqyy_app.public.member_retention_clue,不经过 FDW
小程序 无影响。小程序通过后端 API 间接访问
管理后台 无影响
正向 FDWfdw_etl 无影响。两个方向的 FDW 配置完全独立
业务库 member_retention_clue 无影响。FDW 为只读映射,不修改源表

幂等性说明

CREATE FOREIGN TABLE IF NOT EXISTS 确保重复执行不会报错。如需更新列定义(如添加 source 列),需先 DROP FOREIGN TABLE 再重建,或使用 ALTER FOREIGN TABLE ADD COLUMN


5. 回滚策略

5.1 完整回滚(按逆序执行)

-- 在 etl_feiqiu生产中执行
ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_app REVOKE SELECT ON TABLES FROM etl_user;
REVOKE SELECT ON ALL TABLES IN SCHEMA fdw_app FROM etl_user;
REVOKE USAGE ON SCHEMA fdw_app FROM etl_user;
DROP FOREIGN TABLE IF EXISTS fdw_app.member_retention_clue;
DROP SCHEMA IF EXISTS fdw_app CASCADE;
DROP USER MAPPING IF EXISTS FOR etl_user SERVER zqyy_app_server;
DROP SERVER IF EXISTS zqyy_app_server CASCADE;
-- 注意:如果其他外部表也使用 postgres_fdw不要执行 DROP EXTENSION
-- 在 test_etl_feiqiu测试中执行
ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_app REVOKE SELECT ON TABLES FROM etl_user;
REVOKE SELECT ON ALL TABLES IN SCHEMA fdw_app FROM etl_user;
REVOKE USAGE ON SCHEMA fdw_app FROM etl_user;
DROP FOREIGN TABLE IF EXISTS fdw_app.member_retention_clue;
DROP SCHEMA IF EXISTS fdw_app CASCADE;
DROP USER MAPPING IF EXISTS FOR etl_user SERVER test_zqyy_app_server;
DROP SERVER IF EXISTS test_zqyy_app_server CASCADE;

5.2 仅删除外部表(保留 FDW 基础设施)

DROP FOREIGN TABLE IF EXISTS fdw_app.member_retention_clue;

回滚无数据丢失风险:外部表不存储数据,仅为远程表的映射定义。


6. 验证 SQL

以下 SQL 在 ETL 库(etl_feiqiutest_etl_feiqiu)中执行:

-- 1. 确认 postgres_fdw 扩展已安装
SELECT extname, extversion
  FROM pg_extension
 WHERE extname = 'postgres_fdw';
-- 预期1 行

-- 2. 确认外部服务器存在
-- 生产:
SELECT srvname, srvoptions FROM pg_foreign_server WHERE srvname = 'zqyy_app_server';
-- 测试:
SELECT srvname, srvoptions FROM pg_foreign_server WHERE srvname = 'test_zqyy_app_server';
-- 预期1 行srvoptions 包含正确的 host/dbname/port

-- 3. 确认用户映射存在
SELECT um.umid, r.rolname AS local_role, s.srvname, um.umoptions
  FROM pg_user_mappings um
  JOIN pg_foreign_server s ON s.srvname = um.srvname
  JOIN pg_roles r ON r.rolname = um.usename
 WHERE s.srvname IN ('zqyy_app_server', 'test_zqyy_app_server')
   AND r.rolname = 'etl_user';
-- 预期1 行

-- 4. 确认 fdw_app schema 存在
SELECT schema_name
  FROM information_schema.schemata
 WHERE schema_name = 'fdw_app';
-- 预期1 行

-- 5. 确认外部表列结构完整(当前 9 列)
SELECT column_name, data_type
  FROM information_schema.columns
 WHERE table_schema = 'fdw_app'
   AND table_name = 'member_retention_clue'
 ORDER BY ordinal_position;
-- 预期9 行id, member_id, category, summary, detail,
--              recorded_by_assistant_id, recorded_by_name, recorded_at, site_id

-- 6. 确认外部表在 information_schema.foreign_tables 中注册
SELECT foreign_table_schema, foreign_table_name, foreign_server_name
  FROM information_schema.foreign_tables
 WHERE foreign_table_schema = 'fdw_app'
   AND foreign_table_name = 'member_retention_clue';
-- 预期1 行

-- 7. 确认 etl_user 对 fdw_app 有 USAGE 权限
SELECT has_schema_privilege('etl_user', 'fdw_app', 'USAGE') AS has_usage;
-- 预期true

-- 8. 确认外部表可读取(需业务库侧表已存在且网络连通)
SELECT COUNT(*) FROM fdw_app.member_retention_clue;
-- 预期:返回行数(可能为 0

-- 9. 确认 ALTER DEFAULT PRIVILEGES 已设置
SELECT n.nspname AS schema_name, d.defaclacl AS default_acl
  FROM pg_default_acl d
  JOIN pg_namespace n ON n.oid = d.defaclnamespace
 WHERE n.nspname = 'fdw_app';
-- 预期1 行default_acl 包含 etl_user 的 SELECT 权限

7. 已知差异与待办

项目 状态 说明
source 列缺失 ⚠️ 待同步 业务库侧已有 source VARCHAR(20) NOT NULL DEFAULT 'manual'2026-02-27FDW 外部表定义未包含。当前无 ETL 任务需要此字段,但未来如需读取线索来源需先更新外部表
DWS 任务消费 📋 待规划 member_birthday_manual 的 DWS 消费逻辑已移除。维客线索的 DWS 聚合任务尚未规划

source 列同步方法(备用)

如需同步 source 列,在 ETL 库中执行:

-- 方法 1ALTER 追加列(推荐,无需重建)
ALTER FOREIGN TABLE fdw_app.member_retention_clue
  ADD COLUMN source VARCHAR(20);

-- 方法 2DROP + 重建(完整重置)
DROP FOREIGN TABLE IF EXISTS fdw_app.member_retention_clue;
CREATE FOREIGN TABLE fdw_app.member_retention_clue (
    id                       BIGINT,
    member_id                BIGINT,
    category                 VARCHAR(20),
    summary                  VARCHAR(200),
    detail                   TEXT,
    recorded_by_assistant_id BIGINT,
    recorded_by_name         VARCHAR(50),
    recorded_at              TIMESTAMPTZ,
    site_id                  BIGINT,
    source                   VARCHAR(20)
) SERVER zqyy_app_server
  OPTIONS (schema_name 'public', table_name 'member_retention_clue');

同步后需更新 db/fdw/setup_fdw_reverse.sqldb/fdw/setup_fdw_reverse_test.sql 中的外部表定义。


8. 关联文件

文件 说明
db/fdw/setup_fdw_reverse.sql 生产环境部署脚本(在 etl_feiqiu 中执行)
db/fdw/setup_fdw_reverse_test.sql 测试环境部署脚本(在 test_etl_feiqiu 中执行)
docs/database/BD_Manual_member_retention_clue.md 业务库侧 member_retention_clue 表结构文档
docs/database/BD_Manual_fdw_etl_setup.md 正向 FDW 配置文档(方向相反)
docs/database/BD_Manual_app_schema_rls_views.md ETL 库 app Schema RLS 视图层文档
db/zqyy_app/migrations/2026-02-26__refactor_birthday_to_retention_clue.sql 业务库侧建表迁移脚本