生产环境版本锁定与升级 SOP:从 Ver 号对账到回滚预案驰骋BPM驰骋低代码低代码工作流引擎

生产环境版本锁定与升级 SOP:从 Ver 号对账到回滚预案

这份文档解决什么问题? 对 ccbpm 最常见的抱怨之一是"代码一直在更新,不稳定"。 但源码显示:更新快和自动升级是同一套机制的两面 ------不是产品缺陷,而是运维策略缺位。 本文把这件事固化成一份可执行的 SOP:该锁的锁住,该升的按流程升。

适用:JFlow2026(Java)、CCFlowForNetcore(.NET Core)、CCFlowVue3(前端)。


0. 先纠正一个认知

"版本不稳定"的真相,来自源码:

源码事实 位置 含义
全局版本号是日期戳 CCFlow/Components/BP.WF/Upgrader.cs:public static int Ver = 2026122308; 单调递增,语义是"2026-12-23 第 08 版"
升级是幂等的 同文件 UpdataCCFlowVer():if (currDBVer >= Ver) return null; 库里版本 ≥ 程序版本则直接跳过,不会重复升级
升级会自动打补丁 同文件:CheckPhysicsTable() / UpdataCCFlowVerSQLScript() 表缺列/结构差异自动补齐
库版本对账 SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver' 程序版本 ≠ 库版本才触发升级

结论:升级机制是健壮的、幂等的、可跳版本升级的。 你真正需要做的不是"阻止升级",而是控制"什么时候升"------也就是锁定版本。

⚠️ 但自动升级不等于可以随意升。生产环境必须走本文流程。


1. 版本锁定:三条铁律

铁律一:生产环境永不跟随 Gitee 主线

  • 开源版在 Gitee 定期发布,商业版在内部 SVN 拿研发中最新代码。
  • "最新"意味着未经过你的回归测试 。生产只用你验证过的那个版本。

铁律二:以 Ver 号 + Git 提交为唯一标识

不要用"上次拉的那版"这种模糊说法。锁版本 = 锁定三样东西:

锁定对象 具体锁定 记录方式
后端代码 Git commit hash / SVN revision 记录到发布单
后端版本号 Upgrader.cs 里的 Ver 值(如 2026122308) 记录到发布单
前端包 CCFlowVue3 构建产物(dist)的构建时间 + commit 记录到发布单

跨栈一致性 :Java 与 .NET 分别有各自的 Ver ,必须分别记录、分别升级。 前端 dist 与后端 API 存在契约,升级后端时必须评估前端是否需同步重建。

铁律三:环境隔离,逐级晋级

复制代码
开发(dev) ──► 测试(test) ──► 预生产(staging) ──► 生产(prod)
   跟随最新       锁定候选版        锁定候选版         锁定正式版

任何版本不得跳过 staging 直接上 prod。


2. 上线前的版本锁定操作

2.1 建立"版本资产"记录(每次发布必填)

建议在项目里维护一份 版本发布单.md(或工单系统),每次发布填写:

markdown 复制代码
## 发布单 vYYYY.MM.DD
- [ ] 后端仓库:JFlow / CCFlowForNetcore
- [ ] 后端 commit:__________________
- [ ] 后端 Ver  :__________________   (Upgrader.cs 中读取)
- [ ] 前端 commit:__________________
- [ ] 前端 dist 构建时间:____________
- [ ] 数据库类型与版本:______________
- [ ] 升级脚本执行结果:______________
- [ ] 回归测试结论:__________________
- [ ] 备份文件位置:__________________

2.2 读出版本号(升级前必做)

bash 复制代码
# 后端 Ver 号
# Java:在 JFlow2026 中查找版本常量
# .NET:CCFlow/Components/BP.WF/Upgrader.cs
grep -n "public static int Ver" Upgrader.cs

# 库里当前版本
SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver';

规则 :库版本 ≥ 程序版本 时,升级会被自动跳过;库版本 < 程序版本 时才会打补丁。


3. 升级操作 SOP

顺序不可颠倒:备份 → 停服(或灰度)→ 换代码 → 触发升级 → 验证 → 观察。

第 0 步:备份(不可跳过)

备份项 说明
全库备份 升级会改表结构(CheckPhysicsTable 自动补列/改列),必须可回滚
应用目录 当前运行的程序包(用于回退)
前端 dist 当前生产包
配置文件 application.properties / jflow.properties / app.config

铁律 :没有可用的全库备份,不得开始升级。

第 1 步:升级代码

Java(JFlow2026):

bash 复制代码
# 拉到锁定的 commit(不要直接拉主线)
git checkout <锁定的commit>
mvn -pl jflow-web -am package
# 产出 jflow-web/target/jflow-web-*.jar 替换旧包

.NET(CCFlowForNetcore):

bash 复制代码
git checkout <锁定的commit>
dotnet publish -c Release

前端(CCFlowVue3):

bash 复制代码
pnpm install
pnpm build          # 产出 dist

第 2 步:触发数据库升级

由 admin 登录后台即自动触发(程序 Ver ≠ 库 Ver 时打补丁)。

复制代码
用 admin 账号登录 → 系统自动比对版本 → 自动执行补丁脚本 → 更新 Sys_Serial

⚠️ SAAS 模式例外 :源码中 UpdataCCFlowVer() 对 CCBPMRunModel.SAAS 直接返回 "info@SAAS模式需要手工升级.",SAAS 需人工升级 ,不会自动跑。 参见 Upgrader.cs 中的分支判断。

第 3 步:验证

验证项 方法
版本号已更新 再次执行 SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver',应等于程序 Ver
核心链路可用 发起 → 待办 → 审批 → 结束,全链路跑一遍
升级日志无报错 检查应用日志
历史数据完好 抽查历史流程实例、表单、附件可正常打开

第 4 步:观察期

升级后 24--48 小时为重点观察期,关注:报错日志、定时任务是否正常、消息是否发出、附件上传下载。


4. 故障处理:自动修复与回滚

4.1 "表缺列"类报错------可能自动愈合

源码注释明确了一个机制:

未走升级登录、只是表缺列时,部分功能第一次报错后 CheckPhysicsTable 可能自动补列,刷新再试。

处理顺序:

  1. 先刷新页面重试一次(可能已自动补列);
  2. 仍报错 → 用 admin 登录后台,强制走一次升级流程;
  3. 仍不行 → 查日志定位缺的表/列,手动补;
  4. 最后手段 → 回滚。

4.2 回滚决策

场景 动作
界面报错但核心流程可用 观察 + 记录,不急着回滚
核心流程阻断 立即回滚(代码 + 数据库)
数据出现异常写入 立即停服回滚,并评估数据修复

回滚步骤(与升级相反):

  1. 停服;
  2. 恢复升级前的全库备份;
  3. 换回旧程序包 + 旧 dist + 旧配置;
  4. 启动验证;
  5. 记录故障原因,进入下一轮修复。

⚠️ 库结构升级可能不可逆 (如 ALTER TABLE ... MODIFY MyPK BIGINT)。 所以备份是唯一可靠的退路,这也是第 0 步不可跳过的原因。

4.3 已知历史问题的现状

历史反馈 当前代码状态 依据
附件主键重复 ✅ 已用防御式兜底修复:主键冲突时自动降级为 GUID 重插 WorkNode.cs:try { athDB_N.DirectInsert(); } catch { athDB_N.setMyPK(DBAccess.GenerGUID()); athDB_N.Insert(); }
表单控件报错 用 admin 登录触发升级;或刷新让 CheckPhysicsTable 自动补列 Upgrader.cs

5. 升级前检查清单(Checklist)

升级前逐项打勾,任何一项不满足则不升级:

复制代码
[ ] 已确认目标版本号(Ver)与 commit,并记录到发布单
[ ] 已在 staging 环境完整验证过该版本
[ ] 已完成全库备份,且验证备份可恢复
[ ] 已备份当前程序包 / dist / 配置文件
[ ] 已评估前端是否需同步重建(API 契约是否变化)
[ ] 已确认当前库版本:SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver'
[ ] 已确认升级窗口(避开业务高峰)
[ ] 已通知相关干系人 / 值班人员
[ ] 非 SAAS 模式(SAAS 需改走人工升级流程)

升级后逐项打勾:

复制代码
[ ] 库版本号已等于程序 Ver 号
[ ] 发起 → 待办 → 审批 → 结束 全链路通过
[ ] 历史流程实例可正常打开(含附件)
[ ] 定时任务正常运行(EnableScheduler=1 时验证 HostURL 可达)
[ ] 日志无异常堆栈
[ ] 观察期(24--48h)无新增报错

6. 常见问题 FAQ

Q1:能不能一直不升级? 可以。源码设计是"库版本 ≥ 程序版本就跳过"。如果当前版本已够用,不必频繁升级。 但长期不升级会累积补丁,未来跨越大版本时风险更高------建议定期(如每季度)在 staging 演练一次。

Q2:升级会不会丢数据? 正常不会。升级只做结构补丁 + 数据源初始化 ,不动业务数据。 但 ALTER TABLE 等操作不可逆 ,所以必须备份。

Q3:为什么官方说"版本控制做得差"? 那是商务语境 (商业版走内部 SVN 拿最新代码,服务付费客户),不是工程自评 。 工程上的版本控制是:全局 Ver + Sys_Serial 对账 + 幂等补丁 + 自动补列,比多数产品更严谨。

Q4:多实例部署升级要注意什么?

  • 升级时建议停掉多余实例,由单实例触发升级,避免并打补丁;
  • 定时任务 EnableScheduler=1 只允许一台实例开启,否则重复执行。

Q5:前端要不要每次跟着后端升? 不一定。当后端 API 契约变化时 才需要重建前端。 升级前用"后端 release note / diff API handler"判断,不确定就全量同版本部署(最稳)。


7. 附:核心机制源码索引

机制 文件 关键行/方法
全局版本号 CCFlow/Components/BP.WF/Upgrader.cs public static int Ver = 2026122308;
升级入口 同上 UpdataCCFlowVer()
幂等判断 同上 if (currDBVer >= Ver) return null;
SAAS 手工升级分支 同上 Glo.CCBPMRunModel == CCBPMRunModel.SAAS
版本号落库 同上 UPDATE Sys_Serial SET IntVal=? WHERE CfgKey='Ver'
表结构自动补齐 同上 CheckPhysicsTable()
附件主键兜底 CCFlow/Components/BP.WF/WF/WorkNode.cs try { DirectInsert(); } catch { setMyPK(GenerGUID()); Insert(); }

相关文档:

  • 系统自动升级
  • JFlow 全局配置
  • .NET 全局配置
  • 《新手 30 分钟上手路径》

8. 一页速记

复制代码
锁定:生产只跑验证过的 Ver + commit,永不跟主线
晋级:dev → test → staging → prod,逐级走
升级:备份 → 换代码 → admin 登录触发 → 验证 → 观察 48h
退路:全库备份是唯一可靠回滚手段(表结构变更不可逆)
例外:SAAS 模式必须人工升级
心态:升级机制本身是幂等、健壮的;要控的是"何时升",不是"能不能升"
相关推荐
QianhangQianping1 天前
WebSocket实时推送+ HTTP 定时轮询:一块大屏两套取数怎么不打架
前端·websocket·网络协议·http·低代码·架构·数据可视化
SL_staff1 天前
3分钟完成业务规则调整:告别代码修改,实现拖拽式逻辑配置
java·低代码·全栈
驰骋工作流4 天前
流程时效考核的表结构:从待办时限到 WF_CH 考核结果驰骋BPM驰骋低代码低代码工作流引擎
android·低代码·rxjava
三号路口4 天前
组件库的版本锁定:升级前先冻住
低代码
QianhangQianping4 天前
一块大屏的数据在浏览器里怎么变成画面:背景、子屏、前景三层结构
前端·低代码·架构·编辑器·数据可视化·大屏可视化
她的男孩4 天前
低代码加字段后表结构怎么同步:预览安全 DDL,高风险变更再强制执行
java·spring boot·低代码
搭贝4 天前
【无标题】
人工智能·低代码·ai·1024程序员节·搭贝