feat: add A-card operations frontend and backend foundation

This commit is contained in:
郑龙捷
2026-09-02 09:54:03 +08:00
parent 9badd3597f
commit ad71259ba5
106 changed files with 12461 additions and 1796 deletions
@@ -0,0 +1,154 @@
# A 卡原始监控指标——模型方表评估清单 V0.1
> 日期:2026-09-01
> 评估对象:模型方 `model_deploy` 数据库及待补监控结构。
> 目的:确认模型方能够提供哪些原始监控数据、通过哪些表提供,以及我方是否需要保留标准化月度快照。
## 1. 结论先行
模型方现有 `model_monitor_aggr` 只能部分承载 KS、PSI、IV 等标量指标,不能完整支撑 A 卡运维平台的月度监控、规则回放、报告和特征分布展示。
建议模型方提供 4 类结构化监控表或完全等价的数据结构:
1. `model_monitor_batch`:月度批次、修订和发布状态。
2. `model_monitor_result`:模型单月排序性、KS、PSI和样本量。
3. `model_monitor_feature_metric`:特征级IV、CSI及变化。
4. `model_monitor_distribution`:评分分箱和特征分箱分布。
以上数据应由模型计算任务自动写入,不由模型团队手工执行 SQL。
## 2. 模型方现有相关表
| 现有表 | 当前用途 | 可复用内容 | 不足 | 我方建议 |
|---|---|---|---|---|
| `model_deploy` | 模型部署主表 | `deployId`、模型名称、编码、状态、当前版本 | 缺业务模型大类、银行关系、通用模型等 | 作为模型主标识使用,不复制主表 |
| `model_version` | 模型版本 | 版本ID、版本号、版本名称、创建人、创建时间 | 缺迭代、陪跑、上线/下线和开发指标 | 作为版本主标识;缺失字段另补 |
| `model_details` | 模型详情 | 模型说明、输入/输出Schema | 不是月度监控数据 | 仅模型详情页读取 |
| `model_monitor_aggr` | 通用聚合指标 | `deployId/version/metricName/dimensionValue/valueNum/gmtCreated`;注释允许 `ks/psi/iv` | 无月份、批次、修订、发布状态、排序性、样本量、CSI、分箱结构 | 可继续保存运行聚合;不建议单独承担业务监控全量数据 |
| `model_monitor_call_log` | 模型调用原始日志 | 调用成功、耗时、节点、错误 | 属于服务运行监控,不是模型效果监控 | 不作为 A 卡月度监控来源 |
| `model_monitor_aggr_cursor` | 聚合器游标 | 聚合进度 | 纯技术状态 | 我方无需读取 |
## 3. 建议模型方提供的 4 张表
### 3.1 `model_monitor_batch`——监控批次
一行代表一次月度监控数据发布。
建议字段:
- `id BIGINT`:批次主键。
- `source_batch_no VARCHAR(128)`:模型方幂等批次号。
- `monitor_month DATE`:监控月份,固定当月1日。
- `revision_no INT`:同月份修订号。
- `status VARCHAR(24)``writing/published/failed/superseded`
- `expected_model_count/written_model_count`:预期和实际模型数。
- `feature_row_count/distribution_row_count`:特征和分箱行数。
- `checksum VARCHAR(64)`:批次校验和。
- `generated_at/published_at DATETIME`:计算和发布时间。
- `failed_reason VARCHAR(2000)`:失败原因。
关键约束:同一监控月份和修订号唯一;我方只读取 `published` 的最高修订。
### 3.2 `model_monitor_result`——模型单月监控结果
一行代表一个模型版本在一个月份的核心监控结果。
建议字段:
- `id BIGINT`:结果主键。
- `batch_id BIGINT`:所属批次。
- `deploy_id BIGINT`:关联 `model_deploy.id`
- `version_id BIGINT`:关联 `model_version.id`
- `monitor_month DATE`:监控月份。
- `ranking_result VARCHAR(24)``matched/unmatched/not_applicable`
- `ks_value DECIMAL(12,8)`KS,建议统一存01比率。
- `psi_value DECIMAL(12,8)`PSI,建议统一存01比率。
- `sample_count/good_count/bad_count BIGINT`:样本量。
- `calculated_at DATETIME`:完成计算时间。
- `extra JSON`:仅用于尚未结构化且已约定的数据,不作为核心字段替代品。
关键约束:同一批次下一个 `deploy_id` 只能有一条结果。
### 3.3 `model_monitor_feature_metric`——特征级指标
一行代表一个监控结果下的一个特征。
建议字段:
- `id BIGINT`:主键。
- `monitor_result_id BIGINT`:关联单月监控结果。
- `feature_code/feature_name`:特征编码和名称。
- `iv_value/previous_iv_value`:当期与上期IV。
- `iv_drop_rate`IV降幅。
- `csi_value/previous_csi_value`:当期与上期CSI。
- `csi_rise_rate`CSI升幅。
- `ks_contribution_change`:对KS变化的贡献。
- `psi_contribution_change`:对PSI变化的贡献。
- `calculated_at DATETIME`:计算时间。
关键约束:同一监控结果下 `feature_code` 唯一。
### 3.4 `model_monitor_distribution`——评分及特征分箱
一行代表一个评分区间或一个特征分箱。
建议字段:
- `id BIGINT`:主键。
- `monitor_result_id BIGINT`:关联单月监控结果。
- `dimension_type VARCHAR(24)``score_band/feature_bin`
- `feature_code/feature_name`:评分分箱时可为空。
- `bin_order/bin_code/bin_label`:分箱顺序、编码和显示名称。
- `reference_period_label`:基准期说明。
- `reference_count/reference_share`:基准期数量和占比。
- `current_count/current_share`:当期数量和占比。
- `good_count/bad_count/bad_rate`:好坏客户数据。
- `psi_component/csi_component`:该分箱对PSI/CSI的贡献。
关键约束:`monitor_result_id + dimension_type + feature_code + bin_order` 唯一。
## 4. 四张表与前端页面关系
| 表 | 模型大类概览 | 监控概览 | 监控详情 | 监控/诊断报告 | 系统同步 |
|---|---|---|---|---|---|
| `model_monitor_batch` | 间接 | 间接 | 间接 | 绑定数据版本 | 展示批次和修订状态 |
| `model_monitor_result` | KS/PSI、趋势、同业均值 | 月度明细和等级输入 | 核心结论与趋势 | 报告核心指标 | 同步主数据 |
| `model_monitor_feature_metric` | 不直接使用 | 可选摘要 | IV/CSI前5及全指标 | 诊断报告特征分析 | 同步特征指标 |
| `model_monitor_distribution` | 不直接使用 | 不直接使用 | 排序性和特征分布 | 报告四张明细表 | 同步分箱数据 |
## 5. 我方可以计算、模型方无需提供的内容
取得上述原始数据后,我方可自行计算:
- 本行平均KS/PSI及同业平均值。
- 近6个月趋势。
- KS环比降幅。
- 近6个月二级异常次数。
- 异常等级及A/B/C监控结果等级。
- 命中原因、处理建议、阈值影响测算。
- 报告正文、待办、催办和缓存数据。
## 6. 必须与模型方确认的 10 项
1. 是否接受新增上述4张表,或提供完全等价的表/视图。
2. `deploy_id`和版本引用使用 `model_version.id` 还是 `version`整数。
3. KS、PSI、IV、CSI统一存01还是0100。
4. 排序性计算方法及枚举值。
5. PSI和CSI基准期规则,是否为滚动基准期。
6. 批次粒度是全月全量、按银行还是按模型。
7. 历史勘误是否新增修订,禁止原地覆盖已发布结果。
8. 特征编码是否跨版本稳定,特征名称变更如何留痕。
9. 首次需要回补多少个月历史数据及预计数据量。
10. 提供一套真实脱敏样例:一个模型、一个月份、完整特征和分箱数据。
## 7. 若模型方不愿新增4张表
最小折中方案:
- `model_monitor_aggr`继续承载KS、PSI、IV、CSI等标量指标。
- 必须固定 `metricName` 字典、单位、月份口径和 `dimensionValue` 规则。
- 仍需新增批次/发布结构以及评分和特征分箱明细结构。
- 不建议把所有数据都塞入 `extra JSON`,否则无法建立稳定索引、约束和验收口径。
该折中方案开发和长期维护成本更高,推荐优先采用4张结构化表。
@@ -0,0 +1,123 @@
# A 卡运维平台功能、页面与表关系 V0.1
> 日期:2026-09-01
> 依据:对外原型 V1.10、三库边界确认、`model_platform` 18 张表、`model_deploy` 16 张表及银行表待补结论。
> 状态:分析稿;用于共同确认 `model_operations` V0.2,暂不执行删表或改表。
## 1. 当前结论
最终系统由三个数据库组成:
- `model_platform`:模型开发平台,提供统一登录、角色、项目空间、脚本、调度和对象存储。
- `model_deploy`:模型部署平台,提供模型、版本、部署详情、运行节点和聚合监控指标;银行表及模型—银行关系由模型方补充。
- `model_operations`:我方运维业务库,承载判级、处理、报告、流程、文档、配置和操作统计。
已确认从我方库删除重复主数据表:
- `ops_banks`
- `ops_model_instances`
- `ops_model_versions`
删除后,我方目标表为 **21 张**。其中 16 张归属明确,5 张仍需共同决定是否保留为“标准化快照/读模型”。
## 2. 三库关联原则
- 不建立跨数据库物理外键。
- 我方内部主键继续使用 `CHAR(26)` ULID。
- 开发平台引用使用 `platform_user_id/platform_workspace_id CHAR(26)`
- 部署平台引用使用 `deploy_id/deploy_version_id/bank_id BIGINT`,最终类型以模型方银行表为准。
- 报告、判级和流程必须保存生成时快照,不能因为模型方后续修改名称或版本而改变历史。
- 前端不直接访问数据库,全部通过我方后端聚合三个库的数据。
## 3. 前端页面与功能、表关系
对外原型 V1.10 当前共有 **13 个前端页面**,页面与数据关系如下。
| 前端页面 | 主要功能 | 我方表(model_operations | 外部只读表 | 主要写入动作 |
|---|---|---|---|---|
| 我的工作台 | KPI、待办、关注、催办、最近动态 | `ops_monitor_evaluations``ops_monitor_reviews``ops_reports``ops_workflows``ops_workflow_stages``ops_usage_events` | `model_deploy`、银行表;用户显示名来自 `model_platform.users` | 页面本身只读;操作跳转到处理、报告或流程接口 |
| 平台使用统计 | 登录、需求、报告阅读和下载统计 | `ops_usage_events` | `model_platform.users/roles` | 系统自动记录行为事件 |
| 模型大类概览 | 大类卡片、银行筛选、本行/同业 KS/PSI、趋势、等级下钻 | `ops_model_categories``ops_monitor_results``ops_monitor_evaluations` | `model_deploy.model_deploy``model_version`、模型方银行及关系表 | 只读聚合 |
| 已上线模型详情 | 模型版本、开发时点指标、生命周期、评分逻辑、材料入口 | `ops_documents`;必要时读取标准化监控快照 | `model_deploy``model_version``model_details`、银行及关系表;文件来自 `model_platform.storage_objects` | 上传评分逻辑或材料时写 `ops_documents` |
| 模型监控概览 | 月度明细、多维筛选、异常等级和监控结果等级 | `ops_monitor_results``ops_monitor_evaluations``ops_monitor_reviews` | 模型、版本、银行名称来自 `model_deploy` | 只读;处理动作进入复核表 |
| 模型监控详情 | 排序性、KS/PSI、IV/CSI、分布、命中规则、两段处理 | `ops_monitor_results``ops_monitor_feature_metrics``ops_monitor_distributions``ops_monitor_evaluations``ops_monitor_reviews``ops_reports` | `model_deploy``model_version``model_monitor_aggr` | 模型团队初审、业务团队终审写 `ops_monitor_reviews` |
| 监控 / 诊断报告 | 自动生成、模型团队编辑、发送业务团队、导出 | `ops_reports``ops_report_revisions``ops_report_template_versions``ops_prompt_versions``ops_monitor_evaluations` | 模型、版本、银行信息来自 `model_deploy` | 系统建报告;模型团队新增修订并发送;写 Outbox |
| 报告汇总 | 历史报告查询、阅读状态、筛选和导出 | `ops_reports``ops_report_revisions` | 模型、版本、银行信息来自 `model_deploy` | 阅读/下载写 `ops_usage_events` |
| 全流程进度 | 需求发起、七阶段流转、预计日期、复用通用模型、催办 | `ops_workflows``ops_workflow_stages``ops_documents``ops_outbox_events` | 银行、模型、版本来自 `model_deploy`;用户来自 `model_platform` | 业务发起、模型推进、业务确认均写流程表 |
| 文档知识库 | 按银行、模型、版本、环节检索流程材料 | `ops_documents``ops_workflows``ops_workflow_stages` | 文件元数据来自 `model_platform.storage_objects`;模型信息来自 `model_deploy` | 上传/确认材料写 `ops_documents` |
| 监控等级规则 | 13 行规则矩阵、版本发布、回滚、阈值影响测算 | `ops_rule_versions``ops_rule_items``ops_monitor_evaluations``ops_monitor_results` | 模型与银行信息来自 `model_deploy` | 管理员发布规则;系统按新版本生成判级快照 |
| 报告 Prompt 管理 | Prompt 编辑、版本、发布和历史样本回归 | `ops_prompt_versions``ops_prompt_regression_runs``ops_report_template_versions` | 历史监控样本来自部署/运维数据 | 模型团队维护 Prompt;系统写回归结果 |
| 系统配置 | 报告频率、输出日期、模板版本、通知、手动重算 | `ops_bank_report_configs``ops_report_template_versions``ops_outbox_events` | 银行列表来自模型方银行表;角色权限来自 `model_platform` | 管理员修改配置并触发后台事件 |
## 4. 我方 21 张表逐表归属
### 4.1 数据接入与标准化(5 张,均需定案)
| 表 | 作用 | 写入方 | 主要页面 | 当前判断 |
|---|---|---|---|---|
| `ops_model_categories` | 标准A卡/白户A卡/大额A卡/反欺诈评分业务分类 | 我方管理员或种子 | 模型大类概览、规则、流程 | 暂留;若模型方补业务大类字段,可改为映射表 |
| `ops_monitor_batches` | 月度数据批次、修订号和发布状态 | 同步任务 | 监控、报告、系统配置 | 建议保留,模型方当前无批次/修订/发布结构 |
| `ops_monitor_results` | 月度排序性、KS、PSI及样本快照 | 同步任务 | 大类、监控、报告 | 建议保留为标准化月度快照,不由模型团队手工写 |
| `ops_monitor_feature_metrics` | 特征级 IV/CSI及变化 | 同步任务 | 监控详情、诊断报告 | 建议保留;`model_monitor_aggr` 只有通用 metricName,结构不足 |
| `ops_monitor_distributions` | 评分区间和特征分箱分布 | 同步任务 | 监控详情、诊断报告 | 建议保留;模型方当前 SQL 无对应结构 |
### 4.2 判级与处理(4 张,归属明确)
| 表 | 写入方 | 主要页面 |
|---|---|---|
| `ops_rule_versions` | 管理员 | 监控等级规则 |
| `ops_rule_items` | 管理员 | 监控等级规则 |
| `ops_monitor_evaluations` | 判级服务 | 工作台、概览、详情、报告 |
| `ops_monitor_reviews` | 模型团队初审、业务团队终审 | 工作台、监控详情 |
### 4.3 报告与 AI 治理(6 张,归属明确)
| 表 | 写入方 | 主要页面 |
|---|---|---|
| `ops_report_template_versions` | 管理员 | 报告、系统配置 |
| `ops_prompt_versions` | 模型团队/管理员 | Prompt 管理、报告 |
| `ops_prompt_regression_runs` | 回归任务 | Prompt 管理 |
| `ops_reports` | 报告生成服务、模型团队发送 | 报告、报告汇总、工作台 |
| `ops_report_revisions` | 报告生成服务、模型团队编辑 | 报告、报告汇总 |
| `ops_bank_report_configs` | 管理员 | 系统配置 |
### 4.4 流程、材料与使用统计(4 张,归属明确)
| 表 | 写入方 | 主要页面 |
|---|---|---|
| `ops_workflows` | 业务团队发起、流程服务维护 | 全流程进度、工作台 |
| `ops_workflow_stages` | 模型团队/业务团队操作,流程服务落库 | 全流程进度、工作台 |
| `ops_documents` | 模型团队/业务团队上传,文档服务落库 | 流程、知识库、模型详情 |
| `ops_usage_events` | 系统自动记录 | 平台使用统计、报告汇总 |
### 4.5 异步可靠性(2 张,归属明确)
| 表 | 写入方 | 主要用途 |
|---|---|---|
| `ops_outbox_events` | 与业务操作同事务写入 | 判级、报告、提醒、超时、流程通知 |
| `ops_consumer_inbox` | 后台消费者 | 防止任务重复执行 |
## 5. 关键写入责任
- 模型方只写 `model_deploy`,不直接写我方判级、报告和流程表。
- 我方同步任务从 `model_deploy` 读取数据,规范化后写入 4 张 `ops_monitor_*` 快照表。
- 业务团队和模型团队不直接执行 SQL;其页面操作通过后端服务写入复核、报告修订、流程阶段和文档表。
- 管理员通过页面维护规则、模板、Prompt 和按银行配置。
- 后台任务通过 Outbox/Inbox 处理判级、报告生成、催办和超时默认流转。
## 6. 需要共同定案的 5 项
1. **统一身份主源**:前端登录继续以 `model_platform.users/roles/workspaces` 为准,还是改用 `model_deploy.sys_user/sys_project_space`。建议继续使用现有 `model_platform` 登录。
2. **模型大类来源**:模型方是否在 `model_deploy` 增加标准A/白户A/大额A/反欺诈业务分类;若不增加,我方保留 `ops_model_categories` 与部署模型的映射。
3. **监控快照保留**:是否接受我方把 `model_monitor_aggr` 转换为稳定的月度结果、特征和分布快照。建议保留,避免历史报告随源数据变化。
4. **银行关系结构**:模型方补充一对多还是多对多关系。通用模型存在多银行复用,建议 `bank + model_deploy_bank` 两张表。
5. **缺失监控字段**:排序性、CSI、特征分箱、基准期/当期分布、样本量和批次修订由模型方新增结构还是通过固定 `extra JSON` 提供。建议明确字段表,不依赖无约束 JSON。
## 7. 建议的下一步
先不要再次执行 V0.1 完整建表脚本。按本文件共同确认上述 5 项后:
1. 输出 `model_operations` V0.2 正式表清单。
2. 生成 V0.1 → V0.2 的非破坏性迁移 SQL。
3. 给模型方一份只读表、字段和样例数据需求清单。
4. 再生成 ORM 与首条“模型列表—详情—单月监控结果”真实接口。
@@ -0,0 +1,46 @@
# A 卡运维数据库 DBA 授权申请 V0.1
> 目标:现有 `model_platform` 保持不变,新建 `model_operations`。以下为权限范围说明,不包含真实账号名和口令。
## 1. 运维后端
- 现有 `DATABASE_URL`:沿用平台后端连接,用于认证、工作空间和存储;运维代码只查询必要字段。
- 新增 `OPERATIONS_DATABASE_URL`:连接 `model_operations`,读写运维业务表。
- 不申请对 `model_platform` 新增、修改或删除表结构。
建议平台库最小读取范围:
| 表 | 字段/用途 |
|---|---|
| `users` | `user_id/display_name/status/platform_role_id/is_deleted`,明确排除 `password_hash` |
| `roles` | `role_id/role_code/role_name/role_scope/is_deleted` |
| `workspaces` | `workspace_id/workspace_code/workspace_name/status/is_deleted` |
| `workspace_members` | `workspace_id/user_id/role_id/member_status/is_deleted` |
| `storage_objects` | 文件元数据;优先通过现有存储服务访问 |
| `versions/scripts` | 可选关联开发制品,不作为业务模型主数据 |
| `schedules/schedule_runs` | 可选关联模型计算任务,只读运行状态 |
## 2. 模型数据写入方
建议为模型任务使用独立 `MODEL_WRITER_DATABASE_URL`
- `SELECT``ops_model_categories` 和 7 张模型源表。
- `INSERT/UPDATE``ops_banks``ops_model_instances``ops_model_versions``ops_monitor_batches``ops_monitor_results``ops_monitor_feature_metrics``ops_monitor_distributions`
- `INSERT``ops_outbox_events`,事件类型限定为 `monitor_batch.published`
- 不授予 `DELETE`,不授予 15 张运维业务表写权限。
已发布批次后的源结果不可修改,该限制还需由写入服务校验;MySQL 表级授权本身无法按行状态限制 `UPDATE`
## 3. 架构迁移账号
- 仅在发布窗口使用,可对 `model_operations` 执行 DDL 和种子数据脚本。
- 不作为应用运行账号保存到服务配置。
- 不授予对 `model_platform` 的 DDL 权限。
## 4. 审核项
- MySQL 版本需为 8.0,字符集 `utf8mb4`,排序规则 `utf8mb4_0900_ai_ci`
- 确认新库备份、恢复、容量告警和慢查询策略。
- 确认两套连接池上限,避免同一 FastAPI 进程挤满数据库连接。
- 确认 Schedule Executor 何时增加 `model_operations` Outbox 轮询连接。
+26
View File
@@ -0,0 +1,26 @@
# 数据库设计变更记录
## **当前最新版本:V0.1**
### 功能页面表关系 V0.1 · 2026-09-01
- 按三库边界梳理对外原型 V1.10 的 13 个页面、21 张我方目标表及外部只读依赖。
- 明确 16 张运维业务表归属,标出 5 张数据接入/标准化表仍需共同定案。
- 记录页面级读写关系、人工/系统写入责任以及五项 P0 架构决策。
- 当前仅为分析稿,不执行删表、迁移或正式数据写入。
### 原始监控指标模型方表评估清单 V0.1 · 2026-09-01
- 核查 `model_deploy` 现有6张相关表,确认 `model_monitor_aggr` 只能部分提供KS/PSI/IV标量指标。
- 建议模型方新增或提供等价的监控批次、单月结果、特征指标、分箱分布4类结构化表。
- 列出每张表的必要字段、唯一约束、前端用途及10项评估问题。
- 明确本行/同业均值、趋势、判级和报告等衍生结果由我方计算,无需模型方提供。
### V0.1 · 2026-08-31
- 根据现有 `model_platform` 18 张表结构,确认仅复用身份、工作空间、对象存储、脚本版本和调度数据。
- 新增独立 `model_operations` 库,共 24 张表和 1 个当前监控结果视图。
- 模型平台受控写入 7 张源表;判级、复核、报告、流程等 15 张业务表归运维模块独占。
- 新库自带 Outbox/Inbox,不写现有平台事件表;跨库标识只做逻辑引用,不建物理外键。
- SQL 全部采用非破坏式建库建表,并按模块拆分为单文件不超过 500 行。
- 新增 `model_operations-完整建表-V0.1.sql`,只合并新库 24 张表,可在 DBeaver/MySQL 客户端中一次性复制执行;不包含建库、视图或种子数据。
+158
View File
@@ -0,0 +1,158 @@
"""Build the single-file model_operations schema from versioned modules."""
from __future__ import annotations
from pathlib import Path
BASE = Path(__file__).parent
SOURCE_DIR = BASE / "model_operations-V0.1"
OUTPUT = BASE / "model_operations-完整建表-V0.1.sql"
SOURCES = [
"10_reference_and_models.sql",
"20_monitoring_source.sql",
"30_governance_and_reviews.sql",
"40_reports_and_prompts.sql",
"50_workflows_documents_usage.sql",
]
def statements(text: str) -> list[str]:
"""Split SQL safely enough for quotes/backticks and strip line comments."""
output: list[str] = []
current: list[str] = []
quote: str | None = None
line_comment = False
index = 0
while index < len(text):
char = text[index]
next_char = text[index + 1] if index + 1 < len(text) else ""
if line_comment:
if char == "\n":
line_comment = False
current.append(" ")
index += 1
continue
if quote is None and char == "-" and next_char == "-":
line_comment = True
index += 2
continue
if quote:
current.append(char)
if char == quote:
if quote == "'" and next_char == "'":
current.append(next_char)
index += 2
continue
quote = None
index += 1
continue
if char in ("'", "`"):
quote = char
current.append(char)
elif char == ";":
statement = " ".join("".join(current).split())
if statement:
output.append(statement + ";")
current = []
else:
current.append(char)
index += 1
tail = " ".join("".join(current).split())
if tail:
output.append(tail + ";")
return output
def format_create_table(statement: str) -> str:
"""Format one CREATE TABLE compactly while keeping DBeaver-friendly lines."""
open_at = statement.find("(")
if open_at < 0:
return statement
quote: str | None = None
depth = 0
close_at = -1
for index in range(open_at, len(statement)):
char = statement[index]
next_char = statement[index + 1] if index + 1 < len(statement) else ""
if quote:
if char == quote:
if quote == "'" and next_char == "'":
continue
quote = None
continue
if char in ("'", "`"):
quote = char
elif char == "(":
depth += 1
elif char == ")":
depth -= 1
if depth == 0:
close_at = index
break
if close_at < 0:
return statement
body = statement[open_at + 1 : close_at]
parts: list[str] = []
current: list[str] = []
quote = None
depth = 0
for index, char in enumerate(body):
next_char = body[index + 1] if index + 1 < len(body) else ""
if quote:
current.append(char)
if char == quote:
if quote == "'" and next_char == "'":
continue
quote = None
continue
if char in ("'", "`"):
quote = char
current.append(char)
elif char == "(":
depth += 1
current.append(char)
elif char == ")":
depth -= 1
current.append(char)
elif char == "," and depth == 0:
parts.append(" ".join("".join(current).split()))
current = []
else:
current.append(char)
tail_part = " ".join("".join(current).split())
if tail_part:
parts.append(tail_part)
lines = [statement[:open_at].rstrip() + " ("]
for index in range(0, len(parts), 2):
chunk = ", ".join(parts[index : index + 2])
if index + 2 < len(parts):
chunk += ","
lines.append(" " + chunk)
lines.append(") " + statement[close_at + 1 :].strip())
return "\n".join(lines)
def main() -> None:
bundled: list[str] = [
"-- A 卡模型智能运维平台 · model_operations 完整建表 V0.1",
"-- 内容:仅包含新库的 24 张表,不含建库、视图、种子数据或 model_platform 现有表。",
"-- 执行前:请在 DBeaver 中选中 model_operations 作为当前活动数据库。",
"-- DBeaver:请使用“执行 SQL 脚本”(Alt/Option + X),不要选中全文后按 Ctrl/Cmd + Enter。",
"-- 如使用“执行 SQL 语句”,每次只能选中一条 CREATE TABLE 单独执行。",
"",
]
for source_name in SOURCES:
source_statements = statements((SOURCE_DIR / source_name).read_text(encoding="utf-8"))
bundled.append(f"-- ===== {source_name} =====")
for statement in source_statements:
if not statement.lower().startswith("create table "):
continue
bundled.append(format_create_table(statement))
bundled.append("")
OUTPUT.write_text("\n".join(bundled).rstrip() + "\n", encoding="utf-8")
print(f"built {OUTPUT.name}: 24 tables")
if __name__ == "__main__":
main()
@@ -0,0 +1,9 @@
-- A 卡模型智能运维平台独立数据库 V0.1
-- 安全特性:只创建不存在的数据库,不删除、不覆盖现有 model_platform。
CREATE DATABASE IF NOT EXISTS model_operations
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
USE model_operations;
@@ -0,0 +1,127 @@
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_model_categories (
category_code VARCHAR(32) NOT NULL COMMENT 'std/bai/big/afd',
category_name VARCHAR(100) NOT NULL,
sort_order SMALLINT NOT NULL DEFAULT 0,
status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (category_code),
KEY idx_ops_categories_status (status, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='固定模型大类字典,由运维模块维护';
CREATE TABLE IF NOT EXISTS ops_banks (
bank_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
bank_code VARCHAR(64) NOT NULL,
bank_name VARCHAR(150) NOT NULL,
is_wuji_bank TINYINT(1) NOT NULL DEFAULT 0,
bank_status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive',
source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform',
source_bank_ref VARCHAR(128) NULL,
source_updated_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (bank_id),
UNIQUE KEY uk_ops_banks_code (workspace_id, bank_code),
UNIQUE KEY uk_ops_banks_source (
workspace_id, source_system, source_bank_ref
),
KEY idx_ops_banks_workspace_status (
workspace_id, bank_status, is_deleted
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='银行主数据;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_model_instances (
model_instance_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks',
category_code VARCHAR(32) NOT NULL COMMENT '逻辑引用 ops_model_categories',
model_id VARCHAR(128) NOT NULL COMMENT '工作空间内全局唯一业务模型ID',
model_name VARCHAR(200) NOT NULL,
model_status VARCHAR(24) NOT NULL DEFAULT 'normal'
COMMENT 'normal/escort/escort_finished/offline',
current_version_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_versions',
is_common_model TINYINT(1) NOT NULL DEFAULT 0,
common_source_model_id CHAR(26) NULL
COMMENT '复用时逻辑引用通用模型实例',
common_model_name VARCHAR(200) NULL,
source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform',
source_model_ref VARCHAR(128) NULL,
source_updated_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (model_instance_id),
UNIQUE KEY uk_ops_models_business_id (workspace_id, model_id),
UNIQUE KEY uk_ops_models_source (
workspace_id, source_system, source_model_ref
),
KEY fk_ops_models_bank (bank_id),
KEY fk_ops_models_current_version (current_version_id),
KEY fk_ops_models_common_source (common_source_model_id),
KEY idx_ops_models_filters (
workspace_id, category_code, model_status, is_deleted
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='业务模型实例;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_model_versions (
model_version_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
model_instance_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_instances',
version_label VARCHAR(64) NOT NULL COMMENT '例如 v2.3',
version_status VARCHAR(24) NOT NULL DEFAULT 'active'
COMMENT 'draft/escort/active/offline',
platform_versions_id CHAR(26) NULL
COMMENT '可选逻辑引用 model_platform.versions',
developer_user_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
developer_display_name VARCHAR(100) NULL COMMENT '历史展示快照',
development_date DATE NULL,
iteration_start_date DATE NULL,
last_iteration_date DATE NULL,
iteration_reason VARCHAR(1000) NULL,
escort_start_date DATE NULL,
escort_end_date DATE NULL,
online_date DATE NULL,
offline_date DATE NULL,
development_ks DECIMAL(12,8) NULL COMMENT '0-1比率',
development_psi DECIMAL(12,8) NULL COMMENT '0-1比率',
max_lift DECIMAL(12,8) NULL,
scoring_logic_storage_object_id CHAR(26) NULL
COMMENT '逻辑引用 model_platform.storage_objects',
source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform',
source_version_ref VARCHAR(128) NULL,
source_updated_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (model_version_id),
UNIQUE KEY uk_ops_model_versions_label (
model_instance_id, version_label
),
UNIQUE KEY uk_ops_model_versions_source (
workspace_id, source_system, source_version_ref
),
KEY fk_ops_model_versions_model (model_instance_id),
KEY fk_ops_model_versions_platform_version (platform_versions_id),
KEY fk_ops_model_versions_developer (developer_user_id),
KEY idx_ops_model_versions_lifecycle (
workspace_id, version_status, online_date, offline_date
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='模型版本与生命周期;模型平台可受控直写';
@@ -0,0 +1,160 @@
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_monitor_batches (
batch_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform',
source_batch_no VARCHAR(128) NOT NULL COMMENT '来源方幂等批次号',
monitor_month DATE NOT NULL COMMENT '固定存当月1日',
revision_no INT NOT NULL DEFAULT 1,
supersedes_batch_id CHAR(26) NULL COMMENT '逻辑引用上一修订批次',
batch_status VARCHAR(24) NOT NULL DEFAULT 'writing'
COMMENT 'writing/published/failed/superseded',
expected_model_count INT NOT NULL DEFAULT 0,
written_model_count INT NOT NULL DEFAULT 0,
feature_row_count BIGINT NOT NULL DEFAULT 0,
distribution_row_count BIGINT NOT NULL DEFAULT 0,
checksum_sha256 CHAR(64) NULL,
generated_at DATETIME(3) NULL,
published_at DATETIME(3) NULL,
published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
failed_reason VARCHAR(2000) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (batch_id),
UNIQUE KEY uk_ops_monitor_batches_source_no (
workspace_id, source_system, source_batch_no
),
UNIQUE KEY uk_ops_monitor_batches_revision (
workspace_id, source_system, monitor_month, revision_no
),
KEY fk_ops_monitor_batches_supersedes (supersedes_batch_id),
KEY idx_ops_monitor_batches_publish (
workspace_id, batch_status, monitor_month, revision_no
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='月度监控写入批次与发布门闩;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_monitor_results (
monitor_result_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
batch_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_batches',
model_instance_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_instances',
model_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_versions',
monitor_month DATE NOT NULL COMMENT '固定存当月1日',
source_result_ref VARCHAR(128) NULL,
ranking_result VARCHAR(24) NULL
COMMENT 'matched/unmatched/not_applicable',
ks_value DECIMAL(12,8) NULL COMMENT '0-1比率',
psi_value DECIMAL(12,8) NULL COMMENT '0-1比率',
sample_count BIGINT NULL,
good_count BIGINT NULL,
bad_count BIGINT NULL,
source_result_json JSON NULL COMMENT '尚未结构化的可追溯源字段',
source_calculated_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (monitor_result_id),
UNIQUE KEY uk_ops_monitor_results_batch_model (
batch_id, model_instance_id
),
KEY fk_ops_monitor_results_batch (batch_id),
KEY fk_ops_monitor_results_model (model_instance_id),
KEY fk_ops_monitor_results_version (model_version_id),
KEY idx_ops_monitor_results_month (
workspace_id, monitor_month, model_instance_id
),
CONSTRAINT chk_ops_monitor_results_ks
CHECK (ks_value IS NULL OR (ks_value >= 0 AND ks_value <= 1)),
CONSTRAINT chk_ops_monitor_results_psi
CHECK (psi_value IS NULL OR psi_value >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='单模型单月原始监控结果;发布后不可更新';
CREATE TABLE IF NOT EXISTS ops_monitor_feature_metrics (
feature_metric_id CHAR(26) NOT NULL,
monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results',
feature_code VARCHAR(128) NOT NULL,
feature_name VARCHAR(200) NOT NULL,
iv_value DECIMAL(12,8) NULL,
previous_iv_value DECIMAL(12,8) NULL,
iv_drop_rate DECIMAL(12,8) NULL COMMENT '0-1比率',
csi_value DECIMAL(12,8) NULL,
previous_csi_value DECIMAL(12,8) NULL,
csi_rise_rate DECIMAL(12,8) NULL COMMENT '0-1比率',
ks_contribution_change DECIMAL(12,8) NULL,
psi_contribution_change DECIMAL(12,8) NULL,
source_metric_json JSON NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (feature_metric_id),
UNIQUE KEY uk_ops_feature_metrics_result_feature (
monitor_result_id, feature_code
),
KEY fk_ops_feature_metrics_result (monitor_result_id),
KEY idx_ops_feature_metrics_iv_drop (monitor_result_id, iv_drop_rate),
KEY idx_ops_feature_metrics_csi_rise (monitor_result_id, csi_rise_rate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='单月特征级 IV/CSI 与贡献变化;发布后不可更新';
CREATE TABLE IF NOT EXISTS ops_monitor_distributions (
distribution_id CHAR(26) NOT NULL,
monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results',
dimension_type VARCHAR(24) NOT NULL COMMENT 'score_band/feature_bin',
feature_code VARCHAR(128) NOT NULL DEFAULT '' COMMENT '评分分箱时为空串',
feature_name VARCHAR(200) NULL,
bin_order INT NOT NULL,
bin_code VARCHAR(128) NOT NULL,
bin_label VARCHAR(255) NOT NULL,
reference_period_label VARCHAR(64) NULL,
reference_count BIGINT NULL,
reference_share DECIMAL(12,8) NULL COMMENT '0-1比率',
current_count BIGINT NULL,
current_share DECIMAL(12,8) NULL COMMENT '0-1比率',
good_count BIGINT NULL,
bad_count BIGINT NULL,
bad_rate DECIMAL(12,8) NULL COMMENT '0-1比率',
psi_component DECIMAL(12,8) NULL,
csi_component DECIMAL(12,8) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (distribution_id),
UNIQUE KEY uk_ops_distributions_bin (
monitor_result_id, dimension_type, feature_code, bin_order
),
KEY fk_ops_distributions_result (monitor_result_id),
KEY idx_ops_distributions_feature (
monitor_result_id, feature_code, bin_order
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='排序性评分分箱及特征分布;发布后不可更新';
CREATE OR REPLACE VIEW v_ops_current_monitor_results AS
SELECT result_row.*
FROM ops_monitor_results AS result_row
JOIN ops_monitor_batches AS batch_row
ON batch_row.batch_id = result_row.batch_id
JOIN (
SELECT
workspace_id,
source_system,
monitor_month,
MAX(revision_no) AS revision_no
FROM ops_monitor_batches
WHERE batch_status = 'published' AND is_deleted = 0
GROUP BY workspace_id, source_system, monitor_month
) AS latest
ON latest.workspace_id = batch_row.workspace_id
AND latest.source_system = batch_row.source_system
AND latest.monitor_month = batch_row.monitor_month
AND latest.revision_no = batch_row.revision_no
WHERE result_row.is_deleted = 0
AND batch_row.batch_status = 'published'
AND batch_row.is_deleted = 0;
@@ -0,0 +1,177 @@
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_rule_versions (
rule_version_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
category_code VARCHAR(32) NOT NULL DEFAULT '*'
COMMENT '* 表示全部模型大类',
version_label VARCHAR(64) NOT NULL,
rule_status VARCHAR(24) NOT NULL DEFAULT 'draft'
COMMENT 'draft/published/retired',
threshold_json JSON NOT NULL COMMENT 'KS/PSI/环比切点快照',
supersedes_rule_version_id CHAR(26) NULL,
change_note VARCHAR(1000) NULL,
created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
published_at DATETIME(3) NULL,
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (rule_version_id),
UNIQUE KEY uk_ops_rule_versions_label (
workspace_id, category_code, version_label
),
KEY fk_ops_rule_versions_supersedes (supersedes_rule_version_id),
KEY idx_ops_rule_versions_status (
workspace_id, category_code, rule_status, published_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='监控判级规则版本';
CREATE TABLE IF NOT EXISTS ops_rule_items (
rule_item_id CHAR(26) NOT NULL,
rule_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_versions',
sort_order SMALLINT NOT NULL,
ranking_result VARCHAR(24) NOT NULL COMMENT 'matched/unmatched',
ks_band_code VARCHAR(32) NOT NULL,
psi_band_code VARCHAR(32) NOT NULL,
ks_drop_band_code VARCHAR(32) NOT NULL,
conditions_json JSON NULL COMMENT '用于跨档或扩展条件',
abnormal_level VARCHAR(16) NOT NULL
COMMENT 'normal/level1/level2/level3',
monitor_grade CHAR(1) NOT NULL COMMENT 'A/B/C',
secondary_upgrade_threshold SMALLINT NULL
COMMENT '近6月二级异常累计升级阈值',
reason_code VARCHAR(64) NOT NULL,
reason_template VARCHAR(1000) NOT NULL,
action_text VARCHAR(1000) NOT NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (rule_item_id),
UNIQUE KEY uk_ops_rule_items_order (rule_version_id, sort_order),
UNIQUE KEY uk_ops_rule_items_reason (rule_version_id, reason_code),
KEY fk_ops_rule_items_version (rule_version_id),
CONSTRAINT chk_ops_rule_items_grade
CHECK (monitor_grade IN ('A', 'B', 'C'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='规则版本下的判级矩阵行';
CREATE TABLE IF NOT EXISTS ops_monitor_evaluations (
evaluation_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results',
rule_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_versions',
rule_item_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_items',
ks_mom_drop_rate DECIMAL(12,8) NULL COMMENT '0-1比率',
secondary_level2_hits_6m SMALLINT NOT NULL DEFAULT 0,
abnormal_level VARCHAR(16) NOT NULL
COMMENT 'normal/level1/level2/level3',
monitor_grade CHAR(1) NOT NULL COMMENT 'A/B/C',
reason_code VARCHAR(64) NOT NULL,
reason_text_snapshot VARCHAR(2000) NOT NULL,
action_snapshot VARCHAR(2000) NOT NULL,
is_current TINYINT(1) NOT NULL DEFAULT 1,
evaluated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
current_monitor_result_id CHAR(26)
GENERATED ALWAYS AS (
CASE
WHEN is_current = 1 AND is_deleted = 0 THEN monitor_result_id
ELSE NULL
END
) VIRTUAL,
PRIMARY KEY (evaluation_id),
UNIQUE KEY uk_ops_evaluations_result_rule (
monitor_result_id, rule_version_id
),
UNIQUE KEY uk_ops_evaluations_current (current_monitor_result_id),
KEY fk_ops_evaluations_result (monitor_result_id),
KEY fk_ops_evaluations_rule_version (rule_version_id),
KEY fk_ops_evaluations_rule_item (rule_item_id),
KEY idx_ops_evaluations_grade (
workspace_id, monitor_grade, abnormal_level, evaluated_at
),
CONSTRAINT chk_ops_evaluations_grade
CHECK (monitor_grade IN ('A', 'B', 'C'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='按规则版本生成的不可变监控判级快照';
CREATE TABLE IF NOT EXISTS ops_monitor_reviews (
review_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results',
evaluation_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_evaluations',
review_stage VARCHAR(24) NOT NULL
COMMENT 'model_initial/business_final',
review_status VARCHAR(24) NOT NULL DEFAULT 'pending'
COMMENT 'pending/handled/auto_closed',
decision_code VARCHAR(32) NULL COMMENT 'no_action/tune_or_rebuild',
handling_note VARCHAR(2000) NULL COMMENT '手工处理时必填,由服务层校验',
due_at DATETIME(3) NULL,
handled_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
handled_at DATETIME(3) NULL,
auto_closed_at DATETIME(3) NULL,
state_version INT NOT NULL DEFAULT 0,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (review_id),
UNIQUE KEY uk_ops_reviews_result_stage (
monitor_result_id, review_stage
),
KEY fk_ops_reviews_evaluation (evaluation_id),
KEY fk_ops_reviews_handler (handled_by),
KEY idx_ops_reviews_pending (
workspace_id, review_status, review_stage, due_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='模型团队初审与业务团队终审';
CREATE TABLE IF NOT EXISTS ops_outbox_events (
event_id CHAR(26) NOT NULL,
aggregate_type VARCHAR(64) NOT NULL,
aggregate_id VARCHAR(128) NOT NULL,
event_type VARCHAR(128) NOT NULL,
schema_version SMALLINT NOT NULL DEFAULT 1,
payload_json JSON NOT NULL,
event_status VARCHAR(16) NOT NULL DEFAULT 'pending'
COMMENT 'pending/published/failed',
available_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
retry_count INT NOT NULL DEFAULT 0,
trace_id VARCHAR(64) NULL,
idempotency_key VARCHAR(128) NULL,
published_at DATETIME(3) NULL,
last_error VARCHAR(2000) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (event_id),
UNIQUE KEY uk_ops_outbox_idempotency (idempotency_key),
KEY idx_ops_outbox_pending (event_status, available_at, created_at),
KEY idx_ops_outbox_aggregate (aggregate_type, aggregate_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='运维库事务 Outbox;由运维异步执行器轮询';
CREATE TABLE IF NOT EXISTS ops_consumer_inbox (
consumer_name VARCHAR(128) NOT NULL,
event_id CHAR(26) NOT NULL,
process_status VARCHAR(16) NOT NULL DEFAULT 'processing'
COMMENT 'processing/succeeded/failed',
message_id VARCHAR(128) NULL,
processed_at DATETIME(3) NULL,
error_message VARCHAR(2000) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (consumer_name, event_id),
KEY idx_ops_inbox_status (
consumer_name, process_status, created_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='运维异步消费者幂等 Inbox';
@@ -0,0 +1,172 @@
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_report_template_versions (
template_version_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
report_type VARCHAR(24) NOT NULL COMMENT 'monitor/diagnostic',
version_label VARCHAR(64) NOT NULL,
template_status VARCHAR(24) NOT NULL DEFAULT 'draft'
COMMENT 'draft/published/retired',
schema_json JSON NULL COMMENT '报告结构与字段定义',
template_storage_object_id CHAR(26) NULL
COMMENT '逻辑引用 model_platform.storage_objects',
change_note VARCHAR(1000) NULL,
created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
published_at DATETIME(3) NULL,
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (template_version_id),
UNIQUE KEY uk_ops_report_templates_version (
workspace_id, report_type, version_label
),
KEY idx_ops_report_templates_status (
workspace_id, report_type, template_status, published_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='监控/诊断报告模板版本';
CREATE TABLE IF NOT EXISTS ops_prompt_versions (
prompt_version_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
prompt_key VARCHAR(64) NOT NULL COMMENT 'monitor_A/diagnostic_BC 等',
version_label VARCHAR(64) NOT NULL,
prompt_name VARCHAR(200) NOT NULL,
prompt_text LONGTEXT NOT NULL,
prompt_status VARCHAR(24) NOT NULL DEFAULT 'draft'
COMMENT 'draft/review/published/retired',
change_note VARCHAR(1000) NULL,
created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
published_at DATETIME(3) NULL,
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (prompt_version_id),
UNIQUE KEY uk_ops_prompt_versions_label (
workspace_id, prompt_key, version_label
),
KEY idx_ops_prompt_versions_status (
workspace_id, prompt_key, prompt_status, published_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='报告 Prompt 版本';
CREATE TABLE IF NOT EXISTS ops_prompt_regression_runs (
regression_run_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
prompt_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_prompt_versions',
run_no INT NOT NULL,
run_status VARCHAR(24) NOT NULL DEFAULT 'queued'
COMMENT 'queued/running/passed/failed/cancelled',
sample_set_version VARCHAR(64) NOT NULL,
sample_count INT NOT NULL DEFAULT 0,
passed_count INT NOT NULL DEFAULT 0,
failed_count INT NOT NULL DEFAULT 0,
details_json JSON NULL,
started_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
started_at DATETIME(3) NULL,
finished_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (regression_run_id),
UNIQUE KEY uk_ops_prompt_regression_no (prompt_version_id, run_no),
KEY fk_ops_prompt_regression_prompt (prompt_version_id),
KEY idx_ops_prompt_regression_status (
workspace_id, run_status, created_at
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Prompt 回归测试批次与结果摘要';
CREATE TABLE IF NOT EXISTS ops_reports (
report_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
report_no VARCHAR(64) NOT NULL,
monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results',
evaluation_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_evaluations',
report_month DATE NOT NULL COMMENT '固定存当月1日',
report_type VARCHAR(24) NOT NULL COMMENT 'monitor/diagnostic',
report_status VARCHAR(32) NOT NULL DEFAULT 'pending_model_read'
COMMENT 'pending_model_read/editing/sent_business',
template_version_id CHAR(26) NOT NULL,
prompt_version_id CHAR(26) NULL,
current_revision_id CHAR(26) NULL COMMENT '逻辑引用 ops_report_revisions',
output_date DATE NULL,
generated_at DATETIME(3) NULL,
sent_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
sent_at DATETIME(3) NULL,
business_first_read_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
business_first_read_at DATETIME(3) NULL,
state_version INT NOT NULL DEFAULT 0,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (report_id),
UNIQUE KEY uk_ops_reports_no (workspace_id, report_no),
UNIQUE KEY uk_ops_reports_result_type (monitor_result_id, report_type),
KEY fk_ops_reports_evaluation (evaluation_id),
KEY fk_ops_reports_template (template_version_id),
KEY fk_ops_reports_prompt (prompt_version_id),
KEY idx_ops_reports_summary (
workspace_id, report_month, report_type, report_status
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='监控报告与诊断报告主记录';
CREATE TABLE IF NOT EXISTS ops_report_revisions (
report_revision_id CHAR(26) NOT NULL,
report_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_reports',
revision_no INT NOT NULL,
revision_status VARCHAR(24) NOT NULL DEFAULT 'draft'
COMMENT 'draft/saved/sent',
body_json JSON NULL,
body_text LONGTEXT NULL,
source_snapshot_json JSON NOT NULL
COMMENT '生成时指标、规则、模板和Prompt快照',
pdf_storage_object_id CHAR(26) NULL
COMMENT '逻辑引用 model_platform.storage_objects',
excel_storage_object_id CHAR(26) NULL
COMMENT '逻辑引用 model_platform.storage_objects',
edited_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
edited_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (report_revision_id),
UNIQUE KEY uk_ops_report_revisions_no (report_id, revision_no),
KEY fk_ops_report_revisions_report (report_id),
KEY fk_ops_report_revisions_editor (edited_by)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='报告不可变正文修订';
CREATE TABLE IF NOT EXISTS ops_bank_report_configs (
bank_report_config_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks',
report_frequency VARCHAR(24) NOT NULL DEFAULT 'monthly'
COMMENT 'monthly/quarterly/semiannual/annual',
output_day TINYINT UNSIGNED NOT NULL DEFAULT 15,
output_time TIME NOT NULL DEFAULT '06:00:00',
reminder_days SMALLINT UNSIGNED NOT NULL DEFAULT 5,
enabled TINYINT(1) NOT NULL DEFAULT 1,
state_version INT NOT NULL DEFAULT 0,
updated_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (bank_report_config_id),
UNIQUE KEY uk_ops_bank_report_configs_bank (workspace_id, bank_id),
KEY idx_ops_bank_report_configs_due (
workspace_id, enabled, report_frequency, output_day
),
CONSTRAINT chk_ops_bank_report_output_day
CHECK (output_day BETWEEN 1 AND 28)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='按银行设置报告频率、输出日期与提醒时间';
@@ -0,0 +1,142 @@
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_workflows (
workflow_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
request_no VARCHAR(64) NOT NULL,
workflow_title VARCHAR(255) NOT NULL,
bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks',
category_code VARCHAR(32) NOT NULL COMMENT '逻辑引用 ops_model_categories',
model_instance_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_instances',
request_type VARCHAR(32) NOT NULL COMMENT 'new/iterate/rebuild',
development_source VARCHAR(32) NOT NULL DEFAULT 'independent'
COMMENT 'independent/common_reuse',
common_source_model_id CHAR(26) NULL COMMENT '逻辑引用通用模型实例',
current_stage SMALLINT NOT NULL DEFAULT 1,
workflow_status VARCHAR(24) NOT NULL DEFAULT 'active'
COMMENT 'active/completed/cancelled',
initiated_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
initiated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
expected_feedback_at DATETIME(3) NULL,
planned_test_date DATE NULL,
planned_online_date DATE NULL,
completed_at DATETIME(3) NULL,
cancelled_at DATETIME(3) NULL,
state_version INT NOT NULL DEFAULT 0,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (workflow_id),
UNIQUE KEY uk_ops_workflows_request_no (workspace_id, request_no),
KEY fk_ops_workflows_bank (bank_id),
KEY fk_ops_workflows_model (model_instance_id),
KEY fk_ops_workflows_common_source (common_source_model_id),
KEY idx_ops_workflows_filters (
workspace_id, workflow_status, category_code, current_stage, initiated_at
),
CONSTRAINT chk_ops_workflows_stage
CHECK (current_stage BETWEEN 1 AND 8)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='模型新增、迭代或通用模型复用的全流程实例';
CREATE TABLE IF NOT EXISTS ops_workflow_stages (
workflow_stage_id CHAR(26) NOT NULL,
workflow_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_workflows',
stage_no SMALLINT NOT NULL,
stage_name_snapshot VARCHAR(100) NOT NULL,
stage_status VARCHAR(24) NOT NULL DEFAULT 'pending'
COMMENT 'pending/active/waiting_confirmation/completed/skipped',
owner_role_code VARCHAR(64) NOT NULL COMMENT '登录角色代码快照',
planned_at DATETIME(3) NULL,
due_at DATETIME(3) NULL,
started_at DATETIME(3) NULL,
completed_at DATETIME(3) NULL,
completed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
confirmation_required TINYINT(1) NOT NULL DEFAULT 0,
confirmation_status VARCHAR(24) NULL
COMMENT 'pending/confirmed/rejected/not_required',
confirmed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
confirmed_at DATETIME(3) NULL,
stage_note VARCHAR(2000) NULL,
state_version INT NOT NULL DEFAULT 0,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (workflow_stage_id),
UNIQUE KEY uk_ops_workflow_stages_no (workflow_id, stage_no),
KEY fk_ops_workflow_stages_workflow (workflow_id),
KEY idx_ops_workflow_stages_due (stage_status, due_at),
CONSTRAINT chk_ops_workflow_stages_no
CHECK (stage_no BETWEEN 1 AND 7)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='七阶段流程节点实例与确认留痕';
CREATE TABLE IF NOT EXISTS ops_documents (
document_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
workflow_id CHAR(26) NULL COMMENT '逻辑引用 ops_workflows',
workflow_stage_id CHAR(26) NULL COMMENT '逻辑引用 ops_workflow_stages',
model_instance_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_instances',
model_version_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_versions',
document_type VARCHAR(64) NOT NULL,
document_name VARCHAR(255) NOT NULL,
document_version VARCHAR(64) NULL,
source_type VARCHAR(16) NOT NULL COMMENT 'storage/link',
storage_object_id CHAR(26) NULL
COMMENT '逻辑引用 model_platform.storage_objects',
external_url VARCHAR(1500) NULL,
uploaded_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
uploaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
confirmation_required TINYINT(1) NOT NULL DEFAULT 0,
confirmation_status VARCHAR(24) NULL,
confirmed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users',
confirmed_at DATETIME(3) NULL,
metadata_json JSON NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
ON UPDATE CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (document_id),
KEY fk_ops_documents_workflow (workflow_id),
KEY fk_ops_documents_stage (workflow_stage_id),
KEY fk_ops_documents_model (model_instance_id),
KEY fk_ops_documents_version (model_version_id),
KEY fk_ops_documents_storage (storage_object_id),
KEY idx_ops_documents_knowledge (
workspace_id, document_type, model_instance_id, uploaded_at
),
CONSTRAINT chk_ops_documents_source
CHECK (
(source_type = 'storage' AND storage_object_id IS NOT NULL)
OR (source_type = 'link' AND external_url IS NOT NULL)
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='流程材料和文档知识库索引;文件本体复用平台对象存储';
CREATE TABLE IF NOT EXISTS ops_usage_events (
usage_event_id CHAR(26) NOT NULL,
workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces',
user_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users',
role_code_snapshot VARCHAR(64) NULL,
event_type VARCHAR(64) NOT NULL
COMMENT 'login/request_submit/report_read/report_download',
target_type VARCHAR(64) NULL,
target_id VARCHAR(128) NULL,
event_metadata JSON NULL,
occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
deleted_at DATETIME(3) NULL,
PRIMARY KEY (usage_event_id),
KEY idx_ops_usage_events_stats (
workspace_id, occurred_at, event_type, user_id
),
KEY idx_ops_usage_events_target (target_type, target_id, occurred_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='运维平台登录、需求和报告行为事件';
@@ -0,0 +1,21 @@
USE model_operations;
INSERT INTO ops_model_categories (
category_code,
category_name,
sort_order,
status,
is_deleted,
deleted_at
) VALUES
('std', '标准A卡', 10, 'active', 0, NULL),
('bai', '白户A卡', 20, 'active', 0, NULL),
('big', '大额A卡', 30, 'active', 0, NULL),
('afd', '反欺诈评分', 40, 'active', 0, NULL)
ON DUPLICATE KEY UPDATE
category_name = VALUES(category_name),
sort_order = VALUES(sort_order),
status = VALUES(status),
is_deleted = 0,
deleted_at = NULL;
@@ -0,0 +1,55 @@
# model_operations 数据库 V0.1
本目录只提供建库建表脚本,不会修改现有 `model_platform` 库。当前为设计稿,执行生产数据库前仍需 DBA 审核账号、备份和变更窗口。
如需一次性复制执行 24 张新表,直接使用同级文件 `model_operations-完整建表-V0.1.sql`;该文件不包含建库、视图或种子数据。
先将 `model_operations` 设为当前活动数据库,再使用 DBeaver 的“执行 SQL 脚本”(Alt/Option + X)。合并文件不再包含 `USE`Ctrl/Cmd + Enter 仍只适合单条 `CREATE TABLE`
## 执行顺序
```bash
mysql -h <host> -P <port> -u <schema-admin> -p < 00_database.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 10_reference_and_models.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 20_monitoring_source.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 30_governance_and_reviews.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 40_reports_and_prompts.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 50_workflows_documents_usage.sql
mysql -h <host> -P <port> -u <schema-admin> -p model_operations < 60_seed.sql
```
脚本使用 `CREATE DATABASE/TABLE IF NOT EXISTS`,不包含 `DROP``TRUNCATE` 或业务数据删除。索引全部内联在建表语句中,避免 MySQL 8 不支持 `CREATE INDEX IF NOT EXISTS` 的问题。
执行前可运行 `python3 validate_schema.py`,检查 24 张表、1 个视图、文件行数和破坏性语句。
## 两库边界
### model_platform:只读依赖
| 表 | 运维模块用途 | 允许读取的关键字段 |
|---|---|---|
| `users` | 当前用户、处理人和上传人显示 | `user_id/display_name/status/platform_role_id`;禁止读取 `password_hash` |
| `roles` | 登录角色代码和名称 | `role_id/role_code/role_name/role_scope` |
| `workspaces` | 运维数据空间 | `workspace_id/workspace_code/workspace_name/status` |
| `workspace_members` | 校验用户能否访问工作空间 | `workspace_id/user_id/role_id/member_status` |
| `storage_objects` | 报告、评分逻辑和流程材料元数据 | 通过现有存储服务访问,运维表只保存 `storage_object_id` |
| `versions/scripts` | 可选关联模型开发产物 | 仅引用稳定版本和脚本标识,不把它当业务模型版本 |
| `schedules/schedule_runs` | 可选追踪监控计算任务 | 只读任务和运行状态,不直接改调度数据 |
`permissions``role_permissions``upload_sessions`、平台 `outbox_events` 等表不由运维模块直接读写;权限仍由现有登录/权限模块负责。
### model_operations:运维模块自有
- 24 张表:7 张模型源表、15 张运维业务表、2 张独立 Outbox/Inbox 技术表。
- 所有 `workspace_id/user_id/storage_object_id/platform_versions_id` 均为跨库逻辑引用,不建立跨库物理外键。
- 模型平台写入 7 张源表,并可向 `ops_outbox_events` 插入 `monitor_batch.published` 事件;不得写判级、复核、报告和流程表。
- 运维应用拥有本库业务读写权限,但不得更新已发布的原始监控结果。
## 应用连接
后端需要两套连接配置:
- `DATABASE_URL`:现有 `model_platform`,沿用认证、工作空间、存储和调度能力。
- `OPERATIONS_DATABASE_URL`:新建 `model_operations`,承载全部运维业务数据。
首条真实接口只需要后端双连接;异步判级、报告和提醒接入时,再让 Schedule Executor 增加运维库 Outbox 轮询连接。
@@ -0,0 +1,70 @@
"""Static safety and inventory checks for the model_operations V0.1 DDL."""
from __future__ import annotations
import re
from pathlib import Path
BASE = Path(__file__).parent
EXPECTED_TABLES = {
"ops_model_categories",
"ops_banks",
"ops_model_instances",
"ops_model_versions",
"ops_monitor_batches",
"ops_monitor_results",
"ops_monitor_feature_metrics",
"ops_monitor_distributions",
"ops_rule_versions",
"ops_rule_items",
"ops_monitor_evaluations",
"ops_monitor_reviews",
"ops_outbox_events",
"ops_consumer_inbox",
"ops_report_template_versions",
"ops_prompt_versions",
"ops_prompt_regression_runs",
"ops_reports",
"ops_report_revisions",
"ops_bank_report_configs",
"ops_workflows",
"ops_workflow_stages",
"ops_documents",
"ops_usage_events",
}
def main() -> None:
sql_files = sorted(BASE.glob("*.sql"))
combined = "\n".join(path.read_text(encoding="utf-8") for path in sql_files)
tables = {
match.lower()
for match in re.findall(
r"CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+([a-zA-Z0-9_]+)",
combined,
flags=re.IGNORECASE,
)
}
missing = EXPECTED_TABLES - tables
extra = tables - EXPECTED_TABLES
assert not missing, f"missing tables: {sorted(missing)}"
assert not extra, f"unexpected tables: {sorted(extra)}"
assert len(re.findall(r"CREATE\s+OR\s+REPLACE\s+VIEW", combined, re.I)) == 1
assert not re.search(r"\b(DROP|TRUNCATE|DELETE\s+FROM)\b", combined, re.I)
assert not re.search(
r"\b(?:FROM|JOIN|UPDATE|INTO|REFERENCES|TABLE)\s+model_platform\.",
combined,
re.I,
), "cross-database SQL object reference found"
for path in sql_files:
line_count = len(path.read_text(encoding="utf-8").splitlines())
assert line_count <= 500, f"{path.name} exceeds 500 lines"
print(
f"validated {len(sql_files)} SQL files: "
f"{len(tables)} tables, 1 view, no destructive statements"
)
if __name__ == "__main__":
main()
@@ -0,0 +1,40 @@
-- A 卡模型智能运维平台 · model_operations 完整建表 V0.1
-- 内容:仅包含新库的 24 张表,不含建库、视图、种子数据或 model_platform 现有表。
-- 执行前请确认当前账号具备 model_operations 建表权限。
-- DBeaver:请使用“执行 SQL 脚本”(Alt/Option + X),不要选中全文后按 Ctrl/Cmd + Enter。
-- 如使用“执行 SQL 语句”,每次只能选中一条 USE 或 CREATE TABLE 单独执行。
-- ===== 10_reference_and_models.sql =====
USE model_operations;
CREATE TABLE IF NOT EXISTS ops_model_categories ( category_code VARCHAR(32) NOT NULL COMMENT 'std/bai/big/afd', category_name VARCHAR(100) NOT NULL, sort_order SMALLINT NOT NULL DEFAULT 0, status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (category_code), KEY idx_ops_categories_status (status, sort_order) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='固定模型大类字典,由运维模块维护';
CREATE TABLE IF NOT EXISTS ops_banks ( bank_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', bank_code VARCHAR(64) NOT NULL, bank_name VARCHAR(150) NOT NULL, is_wuji_bank TINYINT(1) NOT NULL DEFAULT 0, bank_status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform', source_bank_ref VARCHAR(128) NULL, source_updated_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (bank_id), UNIQUE KEY uk_ops_banks_code (workspace_id, bank_code), UNIQUE KEY uk_ops_banks_source ( workspace_id, source_system, source_bank_ref ), KEY idx_ops_banks_workspace_status ( workspace_id, bank_status, is_deleted ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='银行主数据;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_model_instances ( model_instance_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks', category_code VARCHAR(32) NOT NULL COMMENT '逻辑引用 ops_model_categories', model_id VARCHAR(128) NOT NULL COMMENT '工作空间内全局唯一业务模型ID', model_name VARCHAR(200) NOT NULL, model_status VARCHAR(24) NOT NULL DEFAULT 'normal' COMMENT 'normal/escort/escort_finished/offline', current_version_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_versions', is_common_model TINYINT(1) NOT NULL DEFAULT 0, common_source_model_id CHAR(26) NULL COMMENT '复用时逻辑引用通用模型实例', common_model_name VARCHAR(200) NULL, source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform', source_model_ref VARCHAR(128) NULL, source_updated_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (model_instance_id), UNIQUE KEY uk_ops_models_business_id (workspace_id, model_id), UNIQUE KEY uk_ops_models_source ( workspace_id, source_system, source_model_ref ), KEY fk_ops_models_bank (bank_id), KEY fk_ops_models_current_version (current_version_id), KEY fk_ops_models_common_source (common_source_model_id), KEY idx_ops_models_filters ( workspace_id, category_code, model_status, is_deleted ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='业务模型实例;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_model_versions ( model_version_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', model_instance_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_instances', version_label VARCHAR(64) NOT NULL COMMENT '例如 v2.3', version_status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT 'draft/escort/active/offline', platform_versions_id CHAR(26) NULL COMMENT '可选逻辑引用 model_platform.versions', developer_user_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', developer_display_name VARCHAR(100) NULL COMMENT '历史展示快照', development_date DATE NULL, iteration_start_date DATE NULL, last_iteration_date DATE NULL, iteration_reason VARCHAR(1000) NULL, escort_start_date DATE NULL, escort_end_date DATE NULL, online_date DATE NULL, offline_date DATE NULL, development_ks DECIMAL(12,8) NULL COMMENT '0-1比率', development_psi DECIMAL(12,8) NULL COMMENT '0-1比率', max_lift DECIMAL(12,8) NULL, scoring_logic_storage_object_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.storage_objects', source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform', source_version_ref VARCHAR(128) NULL, source_updated_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (model_version_id), UNIQUE KEY uk_ops_model_versions_label ( model_instance_id, version_label ), UNIQUE KEY uk_ops_model_versions_source ( workspace_id, source_system, source_version_ref ), KEY fk_ops_model_versions_model (model_instance_id), KEY fk_ops_model_versions_platform_version (platform_versions_id), KEY fk_ops_model_versions_developer (developer_user_id), KEY idx_ops_model_versions_lifecycle ( workspace_id, version_status, online_date, offline_date ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模型版本与生命周期;模型平台可受控直写';
-- ===== 20_monitoring_source.sql =====
CREATE TABLE IF NOT EXISTS ops_monitor_batches ( batch_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', source_system VARCHAR(64) NOT NULL DEFAULT 'model_platform', source_batch_no VARCHAR(128) NOT NULL COMMENT '来源方幂等批次号', monitor_month DATE NOT NULL COMMENT '固定存当月1日', revision_no INT NOT NULL DEFAULT 1, supersedes_batch_id CHAR(26) NULL COMMENT '逻辑引用上一修订批次', batch_status VARCHAR(24) NOT NULL DEFAULT 'writing' COMMENT 'writing/published/failed/superseded', expected_model_count INT NOT NULL DEFAULT 0, written_model_count INT NOT NULL DEFAULT 0, feature_row_count BIGINT NOT NULL DEFAULT 0, distribution_row_count BIGINT NOT NULL DEFAULT 0, checksum_sha256 CHAR(64) NULL, generated_at DATETIME(3) NULL, published_at DATETIME(3) NULL, published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', failed_reason VARCHAR(2000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (batch_id), UNIQUE KEY uk_ops_monitor_batches_source_no ( workspace_id, source_system, source_batch_no ), UNIQUE KEY uk_ops_monitor_batches_revision ( workspace_id, source_system, monitor_month, revision_no ), KEY fk_ops_monitor_batches_supersedes (supersedes_batch_id), KEY idx_ops_monitor_batches_publish ( workspace_id, batch_status, monitor_month, revision_no ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='月度监控写入批次与发布门闩;模型平台可受控直写';
CREATE TABLE IF NOT EXISTS ops_monitor_results ( monitor_result_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', batch_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_batches', model_instance_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_instances', model_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_model_versions', monitor_month DATE NOT NULL COMMENT '固定存当月1日', source_result_ref VARCHAR(128) NULL, ranking_result VARCHAR(24) NULL COMMENT 'matched/unmatched/not_applicable', ks_value DECIMAL(12,8) NULL COMMENT '0-1比率', psi_value DECIMAL(12,8) NULL COMMENT '0-1比率', sample_count BIGINT NULL, good_count BIGINT NULL, bad_count BIGINT NULL, source_result_json JSON NULL COMMENT '尚未结构化的可追溯源字段', source_calculated_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (monitor_result_id), UNIQUE KEY uk_ops_monitor_results_batch_model ( batch_id, model_instance_id ), KEY fk_ops_monitor_results_batch (batch_id), KEY fk_ops_monitor_results_model (model_instance_id), KEY fk_ops_monitor_results_version (model_version_id), KEY idx_ops_monitor_results_month ( workspace_id, monitor_month, model_instance_id ), CONSTRAINT chk_ops_monitor_results_ks CHECK (ks_value IS NULL OR (ks_value >= 0 AND ks_value <= 1)), CONSTRAINT chk_ops_monitor_results_psi CHECK (psi_value IS NULL OR psi_value >= 0) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='单模型单月原始监控结果;发布后不可更新';
CREATE TABLE IF NOT EXISTS ops_monitor_feature_metrics ( feature_metric_id CHAR(26) NOT NULL, monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results', feature_code VARCHAR(128) NOT NULL, feature_name VARCHAR(200) NOT NULL, iv_value DECIMAL(12,8) NULL, previous_iv_value DECIMAL(12,8) NULL, iv_drop_rate DECIMAL(12,8) NULL COMMENT '0-1比率', csi_value DECIMAL(12,8) NULL, previous_csi_value DECIMAL(12,8) NULL, csi_rise_rate DECIMAL(12,8) NULL COMMENT '0-1比率', ks_contribution_change DECIMAL(12,8) NULL, psi_contribution_change DECIMAL(12,8) NULL, source_metric_json JSON NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (feature_metric_id), UNIQUE KEY uk_ops_feature_metrics_result_feature ( monitor_result_id, feature_code ), KEY fk_ops_feature_metrics_result (monitor_result_id), KEY idx_ops_feature_metrics_iv_drop (monitor_result_id, iv_drop_rate), KEY idx_ops_feature_metrics_csi_rise (monitor_result_id, csi_rise_rate) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='单月特征级 IV/CSI 与贡献变化;发布后不可更新';
CREATE TABLE IF NOT EXISTS ops_monitor_distributions ( distribution_id CHAR(26) NOT NULL, monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results', dimension_type VARCHAR(24) NOT NULL COMMENT 'score_band/feature_bin', feature_code VARCHAR(128) NOT NULL DEFAULT '' COMMENT '评分分箱时为空串', feature_name VARCHAR(200) NULL, bin_order INT NOT NULL, bin_code VARCHAR(128) NOT NULL, bin_label VARCHAR(255) NOT NULL, reference_period_label VARCHAR(64) NULL, reference_count BIGINT NULL, reference_share DECIMAL(12,8) NULL COMMENT '0-1比率', current_count BIGINT NULL, current_share DECIMAL(12,8) NULL COMMENT '0-1比率', good_count BIGINT NULL, bad_count BIGINT NULL, bad_rate DECIMAL(12,8) NULL COMMENT '0-1比率', psi_component DECIMAL(12,8) NULL, csi_component DECIMAL(12,8) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (distribution_id), UNIQUE KEY uk_ops_distributions_bin ( monitor_result_id, dimension_type, feature_code, bin_order ), KEY fk_ops_distributions_result (monitor_result_id), KEY idx_ops_distributions_feature ( monitor_result_id, feature_code, bin_order ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='排序性评分分箱及特征分布;发布后不可更新';
-- ===== 30_governance_and_reviews.sql =====
CREATE TABLE IF NOT EXISTS ops_rule_versions ( rule_version_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', category_code VARCHAR(32) NOT NULL DEFAULT '*' COMMENT '* 表示全部模型大类', version_label VARCHAR(64) NOT NULL, rule_status VARCHAR(24) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/retired', threshold_json JSON NOT NULL COMMENT 'KS/PSI/环比切点快照', supersedes_rule_version_id CHAR(26) NULL, change_note VARCHAR(1000) NULL, created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', published_at DATETIME(3) NULL, is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (rule_version_id), UNIQUE KEY uk_ops_rule_versions_label ( workspace_id, category_code, version_label ), KEY fk_ops_rule_versions_supersedes (supersedes_rule_version_id), KEY idx_ops_rule_versions_status ( workspace_id, category_code, rule_status, published_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='监控判级规则版本';
CREATE TABLE IF NOT EXISTS ops_rule_items ( rule_item_id CHAR(26) NOT NULL, rule_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_versions', sort_order SMALLINT NOT NULL, ranking_result VARCHAR(24) NOT NULL COMMENT 'matched/unmatched', ks_band_code VARCHAR(32) NOT NULL, psi_band_code VARCHAR(32) NOT NULL, ks_drop_band_code VARCHAR(32) NOT NULL, conditions_json JSON NULL COMMENT '用于跨档或扩展条件', abnormal_level VARCHAR(16) NOT NULL COMMENT 'normal/level1/level2/level3', monitor_grade CHAR(1) NOT NULL COMMENT 'A/B/C', secondary_upgrade_threshold SMALLINT NULL COMMENT '近6月二级异常累计升级阈值', reason_code VARCHAR(64) NOT NULL, reason_template VARCHAR(1000) NOT NULL, action_text VARCHAR(1000) NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (rule_item_id), UNIQUE KEY uk_ops_rule_items_order (rule_version_id, sort_order), UNIQUE KEY uk_ops_rule_items_reason (rule_version_id, reason_code), KEY fk_ops_rule_items_version (rule_version_id), CONSTRAINT chk_ops_rule_items_grade CHECK (monitor_grade IN ('A', 'B', 'C')) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='规则版本下的判级矩阵行';
CREATE TABLE IF NOT EXISTS ops_monitor_evaluations ( evaluation_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results', rule_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_versions', rule_item_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_rule_items', ks_mom_drop_rate DECIMAL(12,8) NULL COMMENT '0-1比率', secondary_level2_hits_6m SMALLINT NOT NULL DEFAULT 0, abnormal_level VARCHAR(16) NOT NULL COMMENT 'normal/level1/level2/level3', monitor_grade CHAR(1) NOT NULL COMMENT 'A/B/C', reason_code VARCHAR(64) NOT NULL, reason_text_snapshot VARCHAR(2000) NOT NULL, action_snapshot VARCHAR(2000) NOT NULL, is_current TINYINT(1) NOT NULL DEFAULT 1, evaluated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, current_monitor_result_id CHAR(26) GENERATED ALWAYS AS ( CASE WHEN is_current = 1 AND is_deleted = 0 THEN monitor_result_id ELSE NULL END ) VIRTUAL, PRIMARY KEY (evaluation_id), UNIQUE KEY uk_ops_evaluations_result_rule ( monitor_result_id, rule_version_id ), UNIQUE KEY uk_ops_evaluations_current (current_monitor_result_id), KEY fk_ops_evaluations_result (monitor_result_id), KEY fk_ops_evaluations_rule_version (rule_version_id), KEY fk_ops_evaluations_rule_item (rule_item_id), KEY idx_ops_evaluations_grade ( workspace_id, monitor_grade, abnormal_level, evaluated_at ), CONSTRAINT chk_ops_evaluations_grade CHECK (monitor_grade IN ('A', 'B', 'C')) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='按规则版本生成的不可变监控判级快照';
CREATE TABLE IF NOT EXISTS ops_monitor_reviews ( review_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results', evaluation_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_evaluations', review_stage VARCHAR(24) NOT NULL COMMENT 'model_initial/business_final', review_status VARCHAR(24) NOT NULL DEFAULT 'pending' COMMENT 'pending/handled/auto_closed', decision_code VARCHAR(32) NULL COMMENT 'no_action/tune_or_rebuild', handling_note VARCHAR(2000) NULL COMMENT '手工处理时必填,由服务层校验', due_at DATETIME(3) NULL, handled_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', handled_at DATETIME(3) NULL, auto_closed_at DATETIME(3) NULL, state_version INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (review_id), UNIQUE KEY uk_ops_reviews_result_stage ( monitor_result_id, review_stage ), KEY fk_ops_reviews_evaluation (evaluation_id), KEY fk_ops_reviews_handler (handled_by), KEY idx_ops_reviews_pending ( workspace_id, review_status, review_stage, due_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模型团队初审与业务团队终审';
CREATE TABLE IF NOT EXISTS ops_outbox_events ( event_id CHAR(26) NOT NULL, aggregate_type VARCHAR(64) NOT NULL, aggregate_id VARCHAR(128) NOT NULL, event_type VARCHAR(128) NOT NULL, schema_version SMALLINT NOT NULL DEFAULT 1, payload_json JSON NOT NULL, event_status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/published/failed', available_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), retry_count INT NOT NULL DEFAULT 0, trace_id VARCHAR(64) NULL, idempotency_key VARCHAR(128) NULL, published_at DATETIME(3) NULL, last_error VARCHAR(2000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (event_id), UNIQUE KEY uk_ops_outbox_idempotency (idempotency_key), KEY idx_ops_outbox_pending (event_status, available_at, created_at), KEY idx_ops_outbox_aggregate (aggregate_type, aggregate_id, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='运维库事务 Outbox;由运维异步执行器轮询';
CREATE TABLE IF NOT EXISTS ops_consumer_inbox ( consumer_name VARCHAR(128) NOT NULL, event_id CHAR(26) NOT NULL, process_status VARCHAR(16) NOT NULL DEFAULT 'processing' COMMENT 'processing/succeeded/failed', message_id VARCHAR(128) NULL, processed_at DATETIME(3) NULL, error_message VARCHAR(2000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (consumer_name, event_id), KEY idx_ops_inbox_status ( consumer_name, process_status, created_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='运维异步消费者幂等 Inbox';
-- ===== 40_reports_and_prompts.sql =====
CREATE TABLE IF NOT EXISTS ops_report_template_versions ( template_version_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', report_type VARCHAR(24) NOT NULL COMMENT 'monitor/diagnostic', version_label VARCHAR(64) NOT NULL, template_status VARCHAR(24) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/retired', schema_json JSON NULL COMMENT '报告结构与字段定义', template_storage_object_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.storage_objects', change_note VARCHAR(1000) NULL, created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', published_at DATETIME(3) NULL, is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (template_version_id), UNIQUE KEY uk_ops_report_templates_version ( workspace_id, report_type, version_label ), KEY idx_ops_report_templates_status ( workspace_id, report_type, template_status, published_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='监控/诊断报告模板版本';
CREATE TABLE IF NOT EXISTS ops_prompt_versions ( prompt_version_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', prompt_key VARCHAR(64) NOT NULL COMMENT 'monitor_A/diagnostic_BC 等', version_label VARCHAR(64) NOT NULL, prompt_name VARCHAR(200) NOT NULL, prompt_text LONGTEXT NOT NULL, prompt_status VARCHAR(24) NOT NULL DEFAULT 'draft' COMMENT 'draft/review/published/retired', change_note VARCHAR(1000) NULL, created_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), published_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', published_at DATETIME(3) NULL, is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (prompt_version_id), UNIQUE KEY uk_ops_prompt_versions_label ( workspace_id, prompt_key, version_label ), KEY idx_ops_prompt_versions_status ( workspace_id, prompt_key, prompt_status, published_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报告 Prompt 版本';
CREATE TABLE IF NOT EXISTS ops_prompt_regression_runs ( regression_run_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', prompt_version_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_prompt_versions', run_no INT NOT NULL, run_status VARCHAR(24) NOT NULL DEFAULT 'queued' COMMENT 'queued/running/passed/failed/cancelled', sample_set_version VARCHAR(64) NOT NULL, sample_count INT NOT NULL DEFAULT 0, passed_count INT NOT NULL DEFAULT 0, failed_count INT NOT NULL DEFAULT 0, details_json JSON NULL, started_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', started_at DATETIME(3) NULL, finished_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (regression_run_id), UNIQUE KEY uk_ops_prompt_regression_no (prompt_version_id, run_no), KEY fk_ops_prompt_regression_prompt (prompt_version_id), KEY idx_ops_prompt_regression_status ( workspace_id, run_status, created_at ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Prompt 回归测试批次与结果摘要';
CREATE TABLE IF NOT EXISTS ops_reports ( report_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', report_no VARCHAR(64) NOT NULL, monitor_result_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_results', evaluation_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_monitor_evaluations', report_month DATE NOT NULL COMMENT '固定存当月1日', report_type VARCHAR(24) NOT NULL COMMENT 'monitor/diagnostic', report_status VARCHAR(32) NOT NULL DEFAULT 'pending_model_read' COMMENT 'pending_model_read/editing/sent_business', template_version_id CHAR(26) NOT NULL, prompt_version_id CHAR(26) NULL, current_revision_id CHAR(26) NULL COMMENT '逻辑引用 ops_report_revisions', output_date DATE NULL, generated_at DATETIME(3) NULL, sent_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', sent_at DATETIME(3) NULL, business_first_read_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', business_first_read_at DATETIME(3) NULL, state_version INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (report_id), UNIQUE KEY uk_ops_reports_no (workspace_id, report_no), UNIQUE KEY uk_ops_reports_result_type (monitor_result_id, report_type), KEY fk_ops_reports_evaluation (evaluation_id), KEY fk_ops_reports_template (template_version_id), KEY fk_ops_reports_prompt (prompt_version_id), KEY idx_ops_reports_summary ( workspace_id, report_month, report_type, report_status ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='监控报告与诊断报告主记录';
CREATE TABLE IF NOT EXISTS ops_report_revisions ( report_revision_id CHAR(26) NOT NULL, report_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_reports', revision_no INT NOT NULL, revision_status VARCHAR(24) NOT NULL DEFAULT 'draft' COMMENT 'draft/saved/sent', body_json JSON NULL, body_text LONGTEXT NULL, source_snapshot_json JSON NOT NULL COMMENT '生成时指标、规则、模板和Prompt快照', pdf_storage_object_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.storage_objects', excel_storage_object_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.storage_objects', edited_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', edited_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (report_revision_id), UNIQUE KEY uk_ops_report_revisions_no (report_id, revision_no), KEY fk_ops_report_revisions_report (report_id), KEY fk_ops_report_revisions_editor (edited_by) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报告不可变正文修订';
CREATE TABLE IF NOT EXISTS ops_bank_report_configs ( bank_report_config_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks', report_frequency VARCHAR(24) NOT NULL DEFAULT 'monthly' COMMENT 'monthly/quarterly/semiannual/annual', output_day TINYINT UNSIGNED NOT NULL DEFAULT 15, output_time TIME NOT NULL DEFAULT '06:00:00', reminder_days SMALLINT UNSIGNED NOT NULL DEFAULT 5, enabled TINYINT(1) NOT NULL DEFAULT 1, state_version INT NOT NULL DEFAULT 0, updated_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (bank_report_config_id), UNIQUE KEY uk_ops_bank_report_configs_bank (workspace_id, bank_id), KEY idx_ops_bank_report_configs_due ( workspace_id, enabled, report_frequency, output_day ), CONSTRAINT chk_ops_bank_report_output_day CHECK (output_day BETWEEN 1 AND 28) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='按银行设置报告频率、输出日期与提醒时间';
-- ===== 50_workflows_documents_usage.sql =====
CREATE TABLE IF NOT EXISTS ops_workflows ( workflow_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', request_no VARCHAR(64) NOT NULL, workflow_title VARCHAR(255) NOT NULL, bank_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_banks', category_code VARCHAR(32) NOT NULL COMMENT '逻辑引用 ops_model_categories', model_instance_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_instances', request_type VARCHAR(32) NOT NULL COMMENT 'new/iterate/rebuild', development_source VARCHAR(32) NOT NULL DEFAULT 'independent' COMMENT 'independent/common_reuse', common_source_model_id CHAR(26) NULL COMMENT '逻辑引用通用模型实例', current_stage SMALLINT NOT NULL DEFAULT 1, workflow_status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT 'active/completed/cancelled', initiated_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', initiated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), expected_feedback_at DATETIME(3) NULL, planned_test_date DATE NULL, planned_online_date DATE NULL, completed_at DATETIME(3) NULL, cancelled_at DATETIME(3) NULL, state_version INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (workflow_id), UNIQUE KEY uk_ops_workflows_request_no (workspace_id, request_no), KEY fk_ops_workflows_bank (bank_id), KEY fk_ops_workflows_model (model_instance_id), KEY fk_ops_workflows_common_source (common_source_model_id), KEY idx_ops_workflows_filters ( workspace_id, workflow_status, category_code, current_stage, initiated_at ), CONSTRAINT chk_ops_workflows_stage CHECK (current_stage BETWEEN 1 AND 8) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模型新增、迭代或通用模型复用的全流程实例';
CREATE TABLE IF NOT EXISTS ops_workflow_stages ( workflow_stage_id CHAR(26) NOT NULL, workflow_id CHAR(26) NOT NULL COMMENT '逻辑引用 ops_workflows', stage_no SMALLINT NOT NULL, stage_name_snapshot VARCHAR(100) NOT NULL, stage_status VARCHAR(24) NOT NULL DEFAULT 'pending' COMMENT 'pending/active/waiting_confirmation/completed/skipped', owner_role_code VARCHAR(64) NOT NULL COMMENT '登录角色代码快照', planned_at DATETIME(3) NULL, due_at DATETIME(3) NULL, started_at DATETIME(3) NULL, completed_at DATETIME(3) NULL, completed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', confirmation_required TINYINT(1) NOT NULL DEFAULT 0, confirmation_status VARCHAR(24) NULL COMMENT 'pending/confirmed/rejected/not_required', confirmed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', confirmed_at DATETIME(3) NULL, stage_note VARCHAR(2000) NULL, state_version INT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (workflow_stage_id), UNIQUE KEY uk_ops_workflow_stages_no (workflow_id, stage_no), KEY fk_ops_workflow_stages_workflow (workflow_id), KEY idx_ops_workflow_stages_due (stage_status, due_at), CONSTRAINT chk_ops_workflow_stages_no CHECK (stage_no BETWEEN 1 AND 7) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='七阶段流程节点实例与确认留痕';
CREATE TABLE IF NOT EXISTS ops_documents ( document_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', workflow_id CHAR(26) NULL COMMENT '逻辑引用 ops_workflows', workflow_stage_id CHAR(26) NULL COMMENT '逻辑引用 ops_workflow_stages', model_instance_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_instances', model_version_id CHAR(26) NULL COMMENT '逻辑引用 ops_model_versions', document_type VARCHAR(64) NOT NULL, document_name VARCHAR(255) NOT NULL, document_version VARCHAR(64) NULL, source_type VARCHAR(16) NOT NULL COMMENT 'storage/link', storage_object_id CHAR(26) NULL COMMENT '逻辑引用 model_platform.storage_objects', external_url VARCHAR(1500) NULL, uploaded_by CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', uploaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), confirmation_required TINYINT(1) NOT NULL DEFAULT 0, confirmation_status VARCHAR(24) NULL, confirmed_by CHAR(26) NULL COMMENT '逻辑引用 model_platform.users', confirmed_at DATETIME(3) NULL, metadata_json JSON NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (document_id), KEY fk_ops_documents_workflow (workflow_id), KEY fk_ops_documents_stage (workflow_stage_id), KEY fk_ops_documents_model (model_instance_id), KEY fk_ops_documents_version (model_version_id), KEY fk_ops_documents_storage (storage_object_id), KEY idx_ops_documents_knowledge ( workspace_id, document_type, model_instance_id, uploaded_at ), CONSTRAINT chk_ops_documents_source CHECK ( (source_type = 'storage' AND storage_object_id IS NOT NULL) OR (source_type = 'link' AND external_url IS NOT NULL) ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='流程材料和文档知识库索引;文件本体复用平台对象存储';
CREATE TABLE IF NOT EXISTS ops_usage_events ( usage_event_id CHAR(26) NOT NULL, workspace_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.workspaces', user_id CHAR(26) NOT NULL COMMENT '逻辑引用 model_platform.users', role_code_snapshot VARCHAR(64) NULL, event_type VARCHAR(64) NOT NULL COMMENT 'login/request_submit/report_read/report_download', target_type VARCHAR(64) NULL, target_id VARCHAR(128) NULL, event_metadata JSON NULL, occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), is_deleted TINYINT(1) NOT NULL DEFAULT 0, deleted_at DATETIME(3) NULL, PRIMARY KEY (usage_event_id), KEY idx_ops_usage_events_stats ( workspace_id, occurred_at, event_type, user_id ), KEY idx_ops_usage_events_target (target_type, target_id, occurred_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='运维平台登录、需求和报告行为事件';
@@ -0,0 +1,544 @@
create table model_platform.consumer_inbox
(
consumer_name varchar(128) not null,
event_id char(26) not null,
process_status varchar(16) default 'processing' not null comment 'processing/succeeded/failed',
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
message_id varchar(128) null comment 'Inbox message ID',
processed_at datetime(3) null,
error_message varchar(2000) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
primary key (consumer_name, event_id)
)
comment '消费者幂等 Inbox,防止 Stream 重投导致重复执行';
create index idx_consumer_inbox_status
on model_platform.consumer_inbox (consumer_name, process_status, created_at);
create table model_platform.data_resources
(
resource_id char(26) not null
primary key,
workspace_id char(26) not null,
storage_object_id char(26) not null,
owner_user_id char(26) not null,
resource_name varchar(255) not null,
visibility varchar(16) default 'private' not null,
status varchar(16) default 'active' not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
description varchar(1000) null,
schema_json json null comment '字段结构、行数等可选元数据',
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null
)
comment '数据资源';
create index idx_data_resources_owner
on model_platform.data_resources (owner_user_id, status);
create index idx_data_resources_workspace
on model_platform.data_resources (workspace_id, visibility, status);
create table model_platform.outbox_events
(
event_id char(26) not null
primary key,
aggregate_type varchar(64) not null,
aggregate_id varchar(128) not null,
event_type varchar(128) not null,
schema_version smallint default 1 not null,
payload_json json not null,
event_status varchar(16) default 'pending' not null comment 'pending/published/failed',
available_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
retry_count int default 0 not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
trace_id varchar(64) null,
idempotency_key varchar(128) null,
published_at datetime(3) null,
last_error varchar(2000) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null
)
comment '事务 Outbox;提交后发布到内部事件总线';
create index idx_outbox_aggregate
on model_platform.outbox_events (aggregate_type, aggregate_id, created_at);
create index idx_outbox_idempotency
on model_platform.outbox_events (idempotency_key);
create index idx_outbox_pending
on model_platform.outbox_events (event_status, available_at, created_at);
create table model_platform.permissions
(
permission_id char(26) not null
primary key,
permission_code varchar(128) not null,
permission_name varchar(100) not null,
module_code varchar(64) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
description varchar(500) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_permissions_code
unique (permission_code)
)
comment '权限点';
create index idx_permissions_module
on model_platform.permissions (module_code);
create table model_platform.role_permissions
(
role_id char(26) not null,
permission_id char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
primary key (role_id, permission_id)
)
comment '角色权限';
create index fk_role_permissions_permission
on model_platform.role_permissions (permission_id);
create table model_platform.roles
(
role_id char(26) not null
primary key,
role_code varchar(64) not null,
role_name varchar(100) not null,
role_scope varchar(16) not null comment 'platform/workspace',
is_builtin tinyint(1) default 0 not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
description varchar(500) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_roles_code
unique (role_code)
)
comment '角色';
create table model_platform.schedule_edges
(
edge_id char(26) not null
primary key,
schedule_id char(26) not null,
source_node_id char(26) not null,
target_node_id char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
condition_expr varchar(1000) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_schedule_edges_pair
unique (schedule_id, source_node_id, target_node_id)
)
comment 'DAG 有向边';
create index fk_schedule_edges_source
on model_platform.schedule_edges (source_node_id);
create index idx_schedule_edges_target
on model_platform.schedule_edges (target_node_id);
create table model_platform.schedule_node_runs
(
node_run_id char(26) not null
primary key,
run_id char(26) not null,
node_id char(26) not null,
versions_id char(26) not null,
attempt_no int default 1 not null,
node_status varchar(24) default 'queued' not null comment 'queued/running/succeeded/failed/skipped/cancelled/timed_out',
state_version int default 0 not null comment '乐观锁版本',
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
started_at datetime(3) null,
finished_at datetime(3) null,
duration_ms bigint null,
exit_code int null,
message varchar(2000) null,
metrics_json json null,
logs_object_id char(26) null,
result_object_id char(26) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_node_runs_attempt
unique (run_id, node_id, attempt_no)
)
comment '调度节点运行与重试';
create index fk_node_runs_logs
on model_platform.schedule_node_runs (logs_object_id);
create index fk_node_runs_node
on model_platform.schedule_node_runs (node_id);
create index fk_node_runs_result
on model_platform.schedule_node_runs (result_object_id);
create index idx_node_runs_status
on model_platform.schedule_node_runs (run_id, node_status);
create index idx_node_runs_version
on model_platform.schedule_node_runs (versions_id);
create table model_platform.schedule_nodes
(
node_id char(26) not null
primary key,
schedule_id char(26) not null,
node_key varchar(64) not null comment '画布内稳定标识',
node_name varchar(255) not null,
versions_id char(26) not null,
python_version varchar(8) default '3.12' not null comment '节点执行 Python 版本(3.8/3.10/3.12',
timeout_seconds int default 600 not null,
retry_count int default 0 not null,
retry_interval_sec int default 5 not null,
position_x decimal(10, 2) default (0.00) not null,
position_y decimal(10, 2) default (0.00) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
arguments_json json null,
env_refs_json json null comment '只存密钥引用,不存明文密钥',
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_schedule_nodes_key
unique (schedule_id, node_key)
)
comment 'DAG 节点,必须引用稳定版本';
create index idx_schedule_nodes_version
on model_platform.schedule_nodes (versions_id);
create table model_platform.schedule_runs
(
run_id char(26) not null
primary key,
schedule_id char(26) not null,
workspace_id char(26) not null,
workflow_version int not null,
trigger_type varchar(16) not null comment 'manual/cron/api/retry',
idempotency_key varchar(128) not null,
run_status varchar(24) default 'queued' not null comment 'queued/running/succeeded/failed/cancelled/timed_out',
state_version int default 0 not null comment '乐观锁版本',
schedule_snapshot json not null comment '执行时 DAG 快照',
queued_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
triggered_by char(26) null,
started_at datetime(3) null,
finished_at datetime(3) null,
duration_ms bigint null,
error_code varchar(64) null,
error_message text null,
logs_object_id char(26) null,
result_object_id char(26) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_schedule_runs_idempotency
unique (idempotency_key)
)
comment '调度运行';
create index fk_schedule_runs_logs
on model_platform.schedule_runs (logs_object_id);
create index fk_schedule_runs_result
on model_platform.schedule_runs (result_object_id);
create index fk_schedule_runs_user
on model_platform.schedule_runs (triggered_by);
create index idx_schedule_runs_schedule
on model_platform.schedule_runs (schedule_id, created_at);
create index idx_schedule_runs_status
on model_platform.schedule_runs (run_status, queued_at);
create index idx_schedule_runs_workspace_status
on model_platform.schedule_runs (workspace_id, run_status, queued_at);
create table model_platform.schedules
(
schedule_id char(26) not null
primary key,
workspace_id char(26) not null,
schedule_name varchar(255) not null,
trigger_type varchar(16) default 'cron' not null comment 'manual/cron/api',
timezone varchar(64) default 'Asia/Shanghai' not null,
enabled tinyint(1) default 0 not null,
workflow_version int default 1 not null,
max_concurrency int default 1 not null,
failure_policy varchar(24) default 'stop' not null comment 'stop/continue',
created_by char(26) not null,
updated_by char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
description varchar(1000) null,
cron_expression varchar(128) null,
last_run_at datetime(3) null,
next_run_at datetime(3) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null
)
comment '调度方案';
create index fk_schedules_created_by
on model_platform.schedules (created_by);
create index fk_schedules_updated_by
on model_platform.schedules (updated_by);
create index idx_schedules_due
on model_platform.schedules (enabled, next_run_at);
create index idx_schedules_workspace
on model_platform.schedules (workspace_id, enabled, updated_at);
create table model_platform.scripts
(
script_id char(26) not null
primary key,
workspace_id char(26) not null,
current_object_id char(26) not null comment '当前工作副本',
owner_user_id char(26) not null,
script_name varchar(255) not null,
script_type varchar(16) not null comment 'python/notebook',
visibility varchar(16) default 'private' not null,
status varchar(16) default 'active' not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
is_deleted tinyint(1) default 0 not null,
is_locked tinyint(1) default 1 not null,
deleted_at datetime(3) null
)
comment '可执行 Python/Notebook 脚本';
create index idx_scripts_owner
on model_platform.scripts (owner_user_id, status);
create index idx_scripts_workspace
on model_platform.scripts (workspace_id, script_type, visibility, status);
create table model_platform.storage_objects
(
storage_object_id char(26) not null
primary key,
workspace_id char(26) not null,
object_type varchar(16) not null comment 'file/directory',
usage_type varchar(32) not null comment 'working_copy/public_script/data_resource/version_artifact/snapshot/run_log/run_result',
storage_backend varchar(16) not null comment 's3',
storage_uri varchar(1500) not null,
file_name varchar(255) not null,
size_bytes bigint default 0 not null,
visibility varchar(16) default 'private' not null comment 'private/workspace/public',
is_immutable tinyint(1) default 0 not null,
object_status varchar(24) default 'available' not null comment 'uploading/available/deleting/deleted/failed',
created_by char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
owner_user_id char(26) null,
relative_path varchar(1024) null comment 'Workspace 相对路径',
path_hash binary(32) null comment 'SHA-256(relative_path),由应用写入',
bucket_name varchar(128) null,
object_key varchar(1024) null,
object_key_hash binary(32) null comment 'SHA-256(object_key),由应用写入',
object_key_hash_active binary(32) as ((case
when (`object_status` = _utf8mb4'available') then `object_key_hash`
else NULL end)) comment 'VIRTUAL generated column used by uk_storage_bucket_key_active',
file_extension varchar(32) null,
mime_type varchar(255) null,
content_hash char(64) null comment 'SHA-256 hex',
object_etag varchar(255) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
trash_key varchar(1100) null comment 'Path inside the trash bucket where the soft-deleted bytes live. Format: ''{source_bucket}/{object_key}'' so a restore is a same-key copy back to the source bucket. NULL while the row is still available.',
constraint uk_storage_bucket_key_active
unique (storage_backend, bucket_name, object_key_hash_active)
)
comment 'Workspace 文件和 RustFS 对象的统一元数据;目录树走 materialized path (relative_path),不要 join 邻接表列——已删除。';
create index fk_storage_created_by
on model_platform.storage_objects (created_by);
create index idx_storage_content_hash
on model_platform.storage_objects (content_hash);
create index idx_storage_owner
on model_platform.storage_objects (owner_user_id, object_status);
create index idx_storage_workspace_path
on model_platform.storage_objects (workspace_id, storage_backend, path_hash);
create index idx_storage_workspace_relative_path
on model_platform.storage_objects (workspace_id, relative_path(255));
create index idx_storage_workspace_usage
on model_platform.storage_objects (workspace_id, usage_type, object_status);
create table model_platform.upload_sessions
(
upload_id char(26) not null
primary key,
workspace_id char(26) not null,
user_id char(26) not null,
idempotency_key varchar(128) not null,
bucket_name varchar(128) not null,
object_key varchar(1024) not null,
object_key_hash binary(32) not null,
upload_status varchar(24) default 'created' not null comment 'created/uploading/completed/expired/aborted/failed',
expires_at datetime(3) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
multipart_upload_id varchar(255) null,
expected_size_bytes bigint null,
expected_hash char(64) null,
content_type varchar(255) null,
storage_object_id char(26) null,
completed_at datetime(3) null,
file_name varchar(255) default '' not null,
usage_type varchar(32) default 'working_copy' not null comment 'data_resource/version_artifact/snapshot/run_log/run_result/working_copy/public_script',
visibility varchar(16) default 'private' not null comment 'private/workspace/public',
is_immutable tinyint(1) default 0 not null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_upload_sessions_idempotency
unique (idempotency_key)
)
comment 'RustFS 预签名上传会话;URL 本身不持久化';
create index fk_upload_sessions_storage_object
on model_platform.upload_sessions (storage_object_id);
create index fk_upload_sessions_user
on model_platform.upload_sessions (user_id);
create index idx_upload_sessions_expiry
on model_platform.upload_sessions (upload_status, expires_at);
create index idx_upload_sessions_object_key
on model_platform.upload_sessions (bucket_name, object_key_hash);
create index idx_upload_sessions_workspace
on model_platform.upload_sessions (workspace_id, user_id, created_at);
create table model_platform.users
(
user_id char(26) not null
primary key,
username varchar(64) not null,
display_name varchar(100) not null,
password_hash varchar(255) not null,
status varchar(16) default 'active' not null comment 'active/disabled/locked',
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
email varchar(255) null,
platform_role_id char(26) null,
avatar_uri varchar(1000) null,
last_login_at datetime(3) null,
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_users_email
unique (email),
constraint uk_users_username
unique (username)
)
comment '平台用户';
create index fk_users_platform_role
on model_platform.users (platform_role_id);
create index idx_users_status
on model_platform.users (status);
create table model_platform.versions
(
versions_id char(26) not null comment '稳定版本唯一 ID'
primary key,
workspace_id char(26) not null,
script_id char(26) not null,
source_object_id char(26) not null comment '发布时的源对象',
artifact_object_id char(26) not null comment 'S3 不可变版本制品',
version_no int not null,
version_label varchar(32) not null comment '例如 v1.0',
source_path varchar(1024) not null comment '发布时路径快照',
artifact_path varchar(1500) not null,
content_hash char(64) not null,
file_size_bytes bigint default 0 not null,
visibility varchar(16) default 'private' not null,
created_by char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
release_note varchar(1000) null,
schedule_hidden_at datetime(3) null comment '从调度稳定版本列表移除的时间;不影响版本和运行历史',
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_versions_artifact
unique (artifact_object_id),
constraint uk_versions_script_hash
unique (script_id, content_hash),
constraint uk_versions_script_no
unique (script_id, version_no)
)
comment '不可变稳定版本;调度节点必须引用 versions_id';
create index fk_versions_source_object
on model_platform.versions (source_object_id);
create index idx_versions_creator
on model_platform.versions (created_by, created_at);
create index idx_versions_workspace_created
on model_platform.versions (workspace_id, created_at);
create table model_platform.workspace_members
(
workspace_id char(26) not null,
user_id char(26) not null,
role_id char(26) not null,
member_status varchar(16) default 'active' not null,
joined_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
primary key (workspace_id, user_id)
)
comment 'Workspace 成员与角色';
create index idx_workspace_members_role
on model_platform.workspace_members (role_id);
create index idx_workspace_members_user
on model_platform.workspace_members (user_id, member_status);
create table model_platform.workspaces
(
workspace_id char(26) not null
primary key,
workspace_code varchar(64) not null,
workspace_name varchar(150) not null,
active_root_uri varchar(1500) not null comment '活动工作区,建议 NFS/PVC/file URI',
quota_bytes bigint default 0 not null comment '0 表示不限额',
used_bytes bigint default 0 not null,
status varchar(24) default 'active' not null comment 'creating/active/suspended/deleting/deleted',
created_by char(26) not null,
created_at datetime(3) default CURRENT_TIMESTAMP(3) not null,
updated_at datetime(3) default CURRENT_TIMESTAMP(3) not null on update CURRENT_TIMESTAMP(3),
description varchar(1000) null,
artifact_bucket varchar(128) null comment 'S3 bucket',
artifact_prefix varchar(512) null comment 'S3 object key prefix',
is_deleted tinyint(1) default 0 not null,
deleted_at datetime(3) null,
constraint uk_workspaces_code
unique (workspace_code)
)
comment 'Workspace';
create index fk_workspaces_created_by
on model_platform.workspaces (created_by);
create index idx_workspaces_status
on model_platform.workspaces (status);