200字
版本控制(Version Control)的发布订阅模型。
2026-03-10
2026-03-10

要实现“修改不影响线上已发布版本”以及“试运行和发布状态流转”,最优雅且扩展性最强的设计方案是采用**主从表(逻辑表 + 版本物理表)**的设计思想。简单来说,就是把“模型的基础信息”和“模型的节点配置及状态”拆分开来。

下面是具体的表结构设计和业务流转逻辑:

一、 表结构设计

我们通常需要两张核心表:model_info(模型主表)和 model_version(模型版本表)。考虑到节点结构的复杂性,节点数据通常以 JSON 格式存在版本表中。

1. 模型主表 (model_info)

这张表代表一个“逻辑模型”,用于在前端的模型管理列表中展示核心信息。它只关心当前真正在线上跑的是哪个版本,以及用户正在编辑的是哪个版本。

SQL

CREATE TABLE model_info (

  id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',

  model_name varchar(100) NOT NULL COMMENT '模型名称',

  model_code varchar(50) NOT NULL COMMENT '模型唯一编码',

  description varchar(255) DEFAULT NULL COMMENT '模型描述',

  current_published_version_id bigint(20) DEFAULT NULL COMMENT '当前已发布的版本ID (用于评级引擎调用)',

  latest_draft_version_id bigint(20) DEFAULT NULL COMMENT '最新草稿/正在编辑的版本ID (用于前端加载画布)',

  created_by varchar(50) DEFAULT NULL COMMENT '创建人',

  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

  updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

  PRIMARY KEY id),

  UNIQUE KEY uk_model_code model_code)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型主表(逻辑模型)';

2. 模型版本表 (model_version)

每一次的发布,都会在这里固化成一条不可变的记录。日常的“保存节点”操作,只会更新处于“草稿”状态的记录。

SQL

CREATE TABLE model_version (

  id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '版本主键ID',

  model_id bigint(20) NOT NULL COMMENT '关联模型主表ID',

  version_num int(11) NOT NULL COMMENT '版本号 (如 1, 2, 3...)',

  status tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态: 0-未发布(草稿), 1-试运行成功(待发布), 2-已发布, 3-历史归档',

  node_config json DEFAULT NULL COMMENT '模型节点配置(存储画布、节点属性、连线等详情数据)',

  created_by varchar(50) DEFAULT NULL COMMENT '创建/修改人',

  created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

  updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

  PRIMARY KEY id),

  KEY idx_model_id model_id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型版本表(物理模型)';

二、 核心业务流转逻辑 (State Machine)

基于上面的表结构,你的业务需求流转如下:

1. 列表展示 (已发布 / 未发布)

查询: 从 model_info 表查询列表。

状态判定: 如果关联的 latest_draft_version_id 的状态是 0 或 1,说明有未发布的修改;如果 latest_draft_version_id 和 current_published_version_id 相等且状态是 2,说明是纯粹的已发布状态。

2. 评级引擎运行老模型

评级任务在执行时,永远只读取 model_info.current_published_version_id 对应的 model_version 记录中的 node_config。

只要你没点“发布”按钮,current_published_version_id 就不会变,评级就依然跑老模型,完美隔离。

3. 编辑与自动保存

当用户点击一个已发布的模型进行编辑,并拖拽修改节点时:

后端校验: 检查 latest_draft_version_id 对应的状态。如果已经是 2 (已发布),说明不能直接改这个版本。

创建新分支: 后端自动在 model_version 中 Insert 一条新数据(版本号 + 1,状态设为 0 草稿),将原本的 node_config 复制过来并应用当前修改。同时更新 model_info.latest_draft_version_id 指向这个新生成的草稿 ID。

后续的修改,只要状态是 0,就一直在该记录上做 UPDATE node_config 操作。

4. 试运行 (Test Run)

运行逻辑:读取 latest_draft_version_id 对应的配置进行跑批试运行。

流转:如果试运行成功,将该 model_version 的状态从 0 (草稿) 更新为 1 (试运行成功)。此时“发布”按钮在前端亮起。如果用户在这个状态下又修改了节点,状态立刻回退到 0。

5. 正式发布 (Publish)

前置条件: latest_draft_version_id 的状态必须是 1 (试运行成功)。

操作流: 1. 开启数据库事务。

2. 将原先旧的已发布版本(如果有)在 model_version 里的状态更新为 3 (历史归档)。

3. 将当前的 latest_draft_version_id 的状态更新为 2 (已发布)。

4. 将 model_info.current_published_version_id 的值更新为当前的 latest_draft_version_id。

5. 提交事务。

三、 扩展建议

由于你经常处理 Java 以及类似 Spring Boot 的技术栈,建议在这种模型设计中加入以下机制:

JSON 结构化与校验: node_config 里的 JSON 结构会随着时间迭代变得复杂。建议在 Java 代码中定义对应的 DTO/VO 对象,利用 Jackson 或 Fastjson 进行严格的反序列化校验,防止脏数据入库。

乐观锁控制: 在 model_version 表中加入 version 字段作为乐观锁。因为“每次修改某个节点都会保存”,前端可能会产生并发的高频自动保存请求,乐观锁可以防止旧的保存请求覆盖新的节点数据。

你看这样的设计是否能完全覆盖你目前的业务场景?如果需要,我可以为你提供一套基于 Spring Boot 的实体类和事务流转代码框架。

评论