ソースを参照

docs(kb): 30 dataxini 段移到 91 + 92 打勾 + 94 对比表列序换

- 30 删 dataxini / RDBMS reader columnType 段(原误放开发规范,定位偏)
- 91 加上面那段(合备忘定位)
- 92 打勾 DATAX_WORKERS 迁入 workers.ini + DS 工作流无 launch-pad 引用确认
- 94 老/新对比表列序翻为新/老

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tianyu.chu 1 週間 前
コミット
4baf1126b7
4 ファイル変更64 行追加60 行削除
  1. 1 34
      kb/30-开发规范.md
  2. 37 0
      kb/91-重构备忘.md
  3. 2 2
      kb/92-重构进度.md
  4. 24 24
      kb/94-重构对比.md

+ 1 - 34
kb/30-开发规范.md

@@ -526,40 +526,7 @@ jobs/ads/trd/
 -- 状态:[待执行 | 已执行 2026-04-14]
 ```
 
-dataxini
-
-sync ini 里 `[reader]` / `[writer]` 的 `dataSource` 字段必须带 `{db_type}/` 前缀,例如 `dataSource = postgresql/prod-hobby`、`dataSource = hdfs/prod-ha`。代码按首段斜杠判 db_type(= 父目录),裸名(`hobby`)会找不到文件。
-
-
-
-
-
--- 作者:xxx
--- 日期:2026-04-14
--- 工单:TPAD-1234
--- 目的:补录 2026-Q1 的退款维度
--- 状态:[待执行 | 已执行 2026-04-14]
-
-
-
-
-
-**执行与回收**:
-
-- 执行入口复用 `bin/spark-sql-starter.py`,不新增脚本
-- 仅通过 DS 一次性工作流或命令行手动触发
-- `fix/` 和 `backfill/` 类脚本上线前必须经过 1 人以上 Review
-
-
-
-### 6.3 DataX ini 配置格式
-
-1. **RDBMS reader 的 `columnType` 当前被完全忽略**:`PostgreSQLReader.load_column`(`postgresql_reader.py:74-76`)、`MySQLReader`、`ClickHouseReader` 都覆盖了基类 `Plugin.load_column`,只读 `column`(字段名列表),`columnType` 不解析;类型靠 JDBC 驱动的 `ResultSetMetaData` 返回。对应的 writer 同样只读 `column`。**只有 HDFS/HBase/Kafka 这类读写文件/非关系型存储的插件**走基类 `Plugin.load_column`(`plugin.py:63-118`),此时 `columnType` 才生效,且字符串字段可省略(基类默认类型是 `string`,见 `plugin.py:77`)。这一条与 kb/20 §8.1 raw 层"DataX ini 不写类型映射"的约定方向一致,但底层机制是上游代码覆盖掉了,不是约定的结果。
-
-**增量/全量区分:**
-
-- `dt=19700101` 或 `query={}` → 全量
-- `query` 中含 `${start_date}`/`${stop_date}` → 增量
+- 
 
 ## 8. 相关文档
 

+ 37 - 0
kb/91-重构备忘.md

@@ -34,3 +34,40 @@ idea 控制台 ← ssh ← m2 bash ← ssh ← <worker> datax.py stdout
 - 进度要 `tail -f` 独立日志文件
 
 并行模式触发三连:USER=bigdata + CURRENT_HOST=RELEASE_HOST + 显式 `-parallel`,任一缺失退串行。
+
+
+
+dataxini
+
+sync ini 里 `[reader]` / `[writer]` 的 `dataSource` 字段必须带 `{db_type}/` 前缀,例如 `dataSource = postgresql/prod-hobby`、`dataSource = hdfs/prod-ha`。代码按首段斜杠判 db_type(= 父目录),裸名(`hobby`)会找不到文件。
+
+
+
+
+
+-- 作者:xxx
+-- 日期:2026-04-14
+-- 工单:TPAD-1234
+-- 目的:补录 2026-Q1 的退款维度
+-- 状态:[待执行 | 已执行 2026-04-14]
+
+
+
+
+
+**执行与回收**:
+
+- 执行入口复用 `bin/spark-sql-starter.py`,不新增脚本
+- 仅通过 DS 一次性工作流或命令行手动触发
+- `fix/` 和 `backfill/` 类脚本上线前必须经过 1 人以上 Review
+
+
+
+### 6.3 DataX ini 配置格式
+
+1. **RDBMS reader 的 `columnType` 当前被完全忽略**:`PostgreSQLReader.load_column`(`postgresql_reader.py:74-76`)、`MySQLReader`、`ClickHouseReader` 都覆盖了基类 `Plugin.load_column`,只读 `column`(字段名列表),`columnType` 不解析;类型靠 JDBC 驱动的 `ResultSetMetaData` 返回。对应的 writer 同样只读 `column`。**只有 HDFS/HBase/Kafka 这类读写文件/非关系型存储的插件**走基类 `Plugin.load_column`(`plugin.py:63-118`),此时 `columnType` 才生效,且字符串字段可省略(基类默认类型是 `string`,见 `plugin.py:77`)。这一条与 kb/20 §8.1 raw 层"DataX ini 不写类型映射"的约定方向一致,但底层机制是上游代码覆盖掉了,不是约定的结果。
+
+**增量/全量区分:**
+
+- `dt=19700101` 或 `query={}` → 全量
+- `query` 中含 `${start_date}`/`${stop_date}` → 增量

+ 2 - 2
kb/92-重构进度.md

@@ -71,7 +71,7 @@
 - [ ] 验证:同一条 SQL 在无 SET、有 SET、命令行 -sc 三种场景下 `spark.conf.get(...)` 返回值符合优先级预期
 - [x] `RELEASE_USER="alvis"` → `RELEASE_USER="bigdata"` 并迁入 `conf/env.sh`
 - [x] `RELEASE_ROOT_DIR="/home/alvis/release"` → `/home/bigdata/release` 并迁入 `conf/env.sh`
-- [ ] `DATAX_WORKERS=(m3 d1 d2 d3 d4)` + 权重 map 迁入 `conf/workers.ini`
+- [x] `DATAX_WORKERS=(m3 d1 d2 d3 d4)` + 权重 map 迁入 `conf/workers.ini`
 - [x] 删除 `whoami == RELEASE_USER` 分流,`LOG_ROOT_DIR` 单值 `${HOME}/log` 放入 `conf/env.sh`(见 `90-重构路线.md` §7.2.1)
 - [ ] 日志路径统一模板 `${LOG_ROOT_DIR}/{module}/{dt}/{file}.log`(3 层)
 - [ ] 实现 `log_path(module, dt, file)` 工具函数(Python / Shell 各一份,单一来源)
@@ -107,7 +107,7 @@
 
 **前置条件**:新业务 SQL(不属于本重构 scope)在生产稳定运行至少一个完整周期,且 DS 工作流已完全切换到 `jobs/`。
 
-- [ ] 确认 DS 工作流已无对 `launch-pad/` 的引用
+- [x] 确认 DS 工作流已无对 `launch-pad/` 的引用
 - [ ] 删除 `launch-pad/` 整个目录
 - [ ] 删除其他已确认废弃的老文件
 

+ 24 - 24
kb/94-重构对比.md

@@ -7,31 +7,31 @@
 
 ### 1.1 对比表(22 项)
 
-| # | 维度 | 老入口 | 新入口 |
+| # | 维度 | 新入口 | 老入口 |
 |---|---|---|---|
-| 1 | 入口文件数 | 5 `.sh` + 3 `.py` 调试壳 + 1 `config-generator.py` = 9(不含独立保留的 `gc-generator.py`)| 2 `.py` + `cli.py` = 3(bin 层已无 .sh 壳) |
-| 2 | 入口组织 | 三层堆叠:`multiple-hive` → `multiple` → `single` | 门面模式:`datax-hive-import-starter.py` / `datax-hdfs-export-starter.py` 两条独立入口 |
-| 3 | 核心语言 | bash 脚本为主,Python 做 ini→json 翻译 | 纯 Python 入口;env 由 `dw_base/__init__.py` 的 `bootstrap_env()` 从 conf/env.sh 注入(单源,Python/Bash 不双解析) |
-| 4 | 参数形态 | `-c/-cd/-gc/-gcd/-jc/-jcd` 6 种输入 + `--override` + 脚本内 5 个硬编码数组 | `-ini <file>` / `-inis <dir>` 两种输入 + 8 个选项 |
-| 5 | 能力边界 | json 路径暴露给调用方(`-c` / `-jc`),用户可能手动管 json | json 是内部中间产物,`conf/datax-json/{job_name}.json` 扁平化,调用方不感知 |
-| 6 | 核心抽象 | shell for 循环 + 函数 | Python 分层:`entry`(门面)→ `batch`(调度)→ `runner`(执行)+ `worker` / `partition` / `path_utils` / `mask` / `cli` 旁支 |
-| 7 | 优雅与否 | `set -e` + command-substitution 静默退出坑;`parse_ddl` 用 `grep "path =" ` 字面子串(多空格对齐就漏);5 个硬编码数组 + `--override` 从未激活;`__contains__(k)` 反 Pythonic | `in` / ConfigParser / os.path 标准用法;NamedTuple / 纯函数 / 闭包分层;类型注解;异常抛堆栈 |
-| 8 | 死代码 | `plugin.py: import pwd` 无引用、`mysql_reader` 顶层 import 已删的 `dw_base.database.mysql_utils`、5 个 `xxx_array=()` 空壳、`--override` case 无作用对象、`conf/datax/config/` 前缀剥离(目录已归档 bak)、`conf/datax/generated` 路径默认值 | 无(单测 47 条覆盖) |
-| 9 | Hive 分区管理 | `parse_ddl` 依赖 ini `path = ` 单空格字面子串、从 path 按 `/` 切段找 `.db` 段 | `partition.parse_ini_partition` 走 `ConfigParser.get('writer', 'path')` 正规读;`.db` 段抽取逻辑同语义但容错更好 |
-| 10 | 分区 dt 计算 | `START_DATE` 但 writer 用 `stop-1` → 不一致(单日范围歧义掩盖、多日范围错位) | `start_date`(业务日),partition + writer 双方对齐;分区内允许含次日漂移(配套 ADR-03 raw 48h 宽窗) |
-| 11 | 字段脱敏 | 不支持;需要在 ini 里自己手写 querySql 用 SQL 表达式脱敏 | `[mask]` 声明式段自动生成 querySql;PG 5 种脱敏(3 静态 `month_trunc` / `md5` / `mask_middle` + 2 动态 `keep_first_{n}` / `keep_last_{n}`),列名白名单防 SQL 注入 |
-| 12 | Workers 配置 | 硬编码在 `init.sh:13-28`(老 m3/d1-d4 列表 + 权重 map) | 外配 `conf/workers.ini`(新 cdhmaster02/cdhnode01-03) |
-| 13 | 日志路径 | 多维派生:`${LOG_ROOT_DIR}/datax/${SRC_DST}/${PROJECT_LAYER_ENV}/${DB_ENV}/${GROUP}/${START_DATE}/${JOB_NAME}.log`,路径含老 `conf/datax/config/` 残留语义 | 扁平化:`${LOG_ROOT_DIR}/datax/${dt}/${job_name}.log`(对齐 kb/90 §7.2.1) |
-| 14 | 日志内容(stdout)| `pretty_print` **带 ANSI 颜色**:`NORM_MGT`(紫)+ `NORM_GRN`(绿)+ `NORM_RED`(红)+ `NORM_YEL`(黄)分区;驱动常量来自 `bin/common/print-constants.sh` + `dw_base/__init__.py` | Python 原生 `print` **无颜色**(颜色丢失仍未补);**关键阶段 print 已补齐**(worker 选中 / gen 起止 / exec 起止 / 任务起止,2026-04-24 落地);DataX JVM 自身日志输出不变;异常改用 `raise RuntimeError` 携堆栈 |
-| 15 | Tee / 独立日志文件 | bash 层 `\| tee LOG`(串行)/ `> LOG 2>&1 &`(并行),shell pipe 天然做到 | Python 层 `runner._run_with_tee` Popen + 行循环 tee(串行 `tee_to=fh` 写文件 + 父 stdout;并行 `stdout=fh` 只写文件)。**2026-04-24 补齐串行独立 log 文件**,行为对齐老 `\| tee LOG_FILE` |
-| 16 | 错误处理 | `set -e` + exit code 透传、出错位置信息含糊 | Python Exception + `subprocess.returncode`,抛 `RuntimeError` 含上下文(ini 名 / 阶段) |
-| 17 | 分布式 | `-random` + `workers.ini` 加权随机 + ssh 分发到 worker | 同(待 kb/93 ADR-02 拍板后可砍 ssh 分发,DS worker group 接管) |
-| 18 | 字段变换 | 无(需源库做或下游 Spark SQL 做) | ini `[mask]` 声明式 + `mask.py` 翻译为 PG `querySql` 内 SQL 表达式,源库端脱敏(合规硬约束:敏感不出业务库) |
-| 19 | 环境依赖 | `init.sh` 硬编码 USER=bigdata / RELEASE_HOST=m3 / DATAX_WORKERS / PYTHON3_PATH / DATAX_HOME 老路径 | 环境全从 `conf/env.sh` + `conf/workers.ini` 读;`bootstrap_env()` 通过 bash 子进程解析 env.sh 注入 `os.environ`(Python / Bash 单源) |
-| 20 | 测试覆盖 | 0 单测 | 47 条单测(path_utils 5 + worker 6 + partition 7 + runner 5 + batch 7 + entry 5 + cli 3 + mask 9) |
-| 21 | 可维护性 | bash 脚本 + 内嵌数组 + 多文件分散,新人上手须看 3+ 脚本理解 `multiple-hive → multiple → single` 调用链;改动易漏同步;无类型注解;错误信息模糊 | Python 分层模块职责单一;类型注解 + docstring;47 单测兜底;异常含上下文 |
-| 22 | 可扩展性 | 加新 reader 要改 `plugin_factory.py` 顶层 import 并扩 registry;加新脱敏类型要手写 querySql 或改 `plugins/reader/*.py` 代码 | 加新脱敏类型只改 `mask.py` 静态字典一行 / 动态正则一条;加新 ssh 命令子命令只在 `cli.py` 加 subparser;`plugin_factory` eager import 未变动(见 kb/90 §2.6 后延 ADR 的"plugin_factory 解耦"低优先级项) |
-| 23 | speed 调参 | `job_config_generator.py:60-67` 硬编码两档时段 + 两档 speed 三参,调优要改代码发布 | 三级注入:L1 `conf/datax-tuning.conf` 默认 + L2 ini `[speed]` 段 + L3 CLI `-channel/-byte/-record`,逐字段合并 + 审计日志(详见 kb/93 ADR-04) |
+| 1 | 入口文件数 | 2 `.py` + `cli.py` = 3(bin 层已无 .sh 壳) | 5 `.sh` + 3 `.py` 调试壳 + 1 `config-generator.py` = 9(不含独立保留的 `gc-generator.py`)|
+| 2 | 入口组织 | 门面模式:`datax-hive-import-starter.py` / `datax-hdfs-export-starter.py` 两条独立入口 | 三层堆叠:`multiple-hive` → `multiple` → `single` |
+| 3 | 核心语言 | 纯 Python 入口;env 由 `dw_base/__init__.py` 的 `bootstrap_env()` 从 conf/env.sh 注入(单源,Python/Bash 不双解析) | bash 脚本为主,Python 做 ini→json 翻译 |
+| 4 | 参数形态 | `-ini <file>` / `-inis <dir>` 两种输入 + 8 个选项 | `-c/-cd/-gc/-gcd/-jc/-jcd` 6 种输入 + `--override` + 脚本内 5 个硬编码数组 |
+| 5 | 能力边界 | json 是内部中间产物,`conf/datax-json/{job_name}.json` 扁平化,调用方不感知 | json 路径暴露给调用方(`-c` / `-jc`),用户可能手动管 json |
+| 6 | 核心抽象 | Python 分层:`entry`(门面)→ `batch`(调度)→ `runner`(执行)+ `worker` / `partition` / `path_utils` / `mask` / `cli` 旁支 | shell for 循环 + 函数 |
+| 7 | 优雅与否 | `in` / ConfigParser / os.path 标准用法;NamedTuple / 纯函数 / 闭包分层;类型注解;异常抛堆栈 | `set -e` + command-substitution 静默退出坑;`parse_ddl` 用 `grep "path =" ` 字面子串(多空格对齐就漏);5 个硬编码数组 + `--override` 从未激活;`__contains__(k)` 反 Pythonic |
+| 8 | 死代码 | 无(单测 47 条覆盖) | `plugin.py: import pwd` 无引用、`mysql_reader` 顶层 import 已删的 `dw_base.database.mysql_utils`、5 个 `xxx_array=()` 空壳、`--override` case 无作用对象、`conf/datax/config/` 前缀剥离(目录已归档 bak)、`conf/datax/generated` 路径默认值 |
+| 9 | Hive 分区管理 | `partition.parse_ini_partition` 走 `ConfigParser.get('writer', 'path')` 正规读;`.db` 段抽取逻辑同语义但容错更好 | `parse_ddl` 依赖 ini `path = ` 单空格字面子串、从 path 按 `/` 切段找 `.db` 段 |
+| 10 | 分区 dt 计算 | `start_date`(业务日),partition + writer 双方对齐;分区内允许含次日漂移(配套 ADR-03 raw 48h 宽窗) | `START_DATE` 但 writer 用 `stop-1` → 不一致(单日范围歧义掩盖、多日范围错位) |
+| 11 | 字段脱敏 | `[mask]` 声明式段自动生成 querySql;PG 5 种脱敏(3 静态 `month_trunc` / `md5` / `mask_middle` + 2 动态 `keep_first_{n}` / `keep_last_{n}`),列名白名单防 SQL 注入 | 不支持;需要在 ini 里自己手写 querySql 用 SQL 表达式脱敏 |
+| 12 | Workers 配置 | 外配 `conf/workers.ini`(新 cdhmaster02/cdhnode01-03) | 硬编码在 `init.sh:13-28`(老 m3/d1-d4 列表 + 权重 map) |
+| 13 | 日志路径 | 扁平化:`${LOG_ROOT_DIR}/datax/${dt}/${job_name}.log`(对齐 kb/90 §7.2.1) | 多维派生:`${LOG_ROOT_DIR}/datax/${SRC_DST}/${PROJECT_LAYER_ENV}/${DB_ENV}/${GROUP}/${START_DATE}/${JOB_NAME}.log`,路径含老 `conf/datax/config/` 残留语义 |
+| 14 | 日志内容(stdout)| Python 原生 `print` **无颜色**(颜色丢失仍未补);**关键阶段 print 已补齐**(worker 选中 / gen 起止 / exec 起止 / 任务起止,2026-04-24 落地);DataX JVM 自身日志输出不变;异常改用 `raise RuntimeError` 携堆栈 | `pretty_print` **带 ANSI 颜色**:`NORM_MGT`(紫)+ `NORM_GRN`(绿)+ `NORM_RED`(红)+ `NORM_YEL`(黄)分区;驱动常量来自 `bin/common/print-constants.sh` + `dw_base/__init__.py` |
+| 15 | Tee / 独立日志文件 | Python 层 `runner._run_with_tee` Popen + 行循环 tee(串行 `tee_to=fh` 写文件 + 父 stdout;并行 `stdout=fh` 只写文件)。**2026-04-24 补齐串行独立 log 文件**,行为对齐老 `\| tee LOG_FILE` | bash 层 `\| tee LOG`(串行)/ `> LOG 2>&1 &`(并行),shell pipe 天然做到 |
+| 16 | 错误处理 | Python Exception + `subprocess.returncode`,抛 `RuntimeError` 含上下文(ini 名 / 阶段) | `set -e` + exit code 透传、出错位置信息含糊 |
+| 17 | 分布式 | 同(待 kb/93 ADR-02 拍板后可砍 ssh 分发,DS worker group 接管) | `-random` + `workers.ini` 加权随机 + ssh 分发到 worker |
+| 18 | 字段变换 | ini `[mask]` 声明式 + `mask.py` 翻译为 PG `querySql` 内 SQL 表达式,源库端脱敏(合规硬约束:敏感不出业务库) | 无(需源库做或下游 Spark SQL 做) |
+| 19 | 环境依赖 | 环境全从 `conf/env.sh` + `conf/workers.ini` 读;`bootstrap_env()` 通过 bash 子进程解析 env.sh 注入 `os.environ`(Python / Bash 单源) | `init.sh` 硬编码 USER=bigdata / RELEASE_HOST=m3 / DATAX_WORKERS / PYTHON3_PATH / DATAX_HOME 老路径 |
+| 20 | 测试覆盖 | 47 条单测(path_utils 5 + worker 6 + partition 7 + runner 5 + batch 7 + entry 5 + cli 3 + mask 9) | 0 单测 |
+| 21 | 可维护性 | Python 分层模块职责单一;类型注解 + docstring;47 单测兜底;异常含上下文 | bash 脚本 + 内嵌数组 + 多文件分散,新人上手须看 3+ 脚本理解 `multiple-hive → multiple → single` 调用链;改动易漏同步;无类型注解;错误信息模糊 |
+| 22 | 可扩展性 | 加新脱敏类型只改 `mask.py` 静态字典一行 / 动态正则一条;加新 ssh 命令子命令只在 `cli.py` 加 subparser;`plugin_factory` eager import 未变动(见 kb/90 §2.6 后延 ADR 的"plugin_factory 解耦"低优先级项) | 加新 reader 要改 `plugin_factory.py` 顶层 import 并扩 registry;加新脱敏类型要手写 querySql 或改 `plugins/reader/*.py` 代码 |
+| 23 | speed 调参 | 三级注入:L1 `conf/datax-tuning.conf` 默认 + L2 ini `[speed]` 段 + L3 CLI `-channel/-byte/-record`,逐字段合并 + 审计日志(详见 kb/93 ADR-04) | `job_config_generator.py:60-67` 硬编码两档时段 + 两档 speed 三参,调优要改代码发布 |
 
 ### 1.2 行为退化说明