生产环境的版本管理,核心不是拒绝更新,而是把「什么时候更新」变成流程:锁定验证过的版本号与提交、按 dev→test→staging→prod 逐级晋级、升级前做全库备份、升级后留观察期,并为不可逆的表结构变更准备回滚路径。
"版本不稳定"的真相,来自源码:
源码事实 | 位置 | 含义 |
|---|---|---|
全局版本号是日期戳 | 引擎流程组件目录/Upgrader.cs:public static int Ver = 2026122308; | 单调递增,语义是"2026-12-23 第 08 版" |
升级是幂等的 | 同文件 UpdataVer():if (currDBVer >= Ver) return null; | 库里版本 ≥ 程序版本则直接跳过,不会重复升级 |
升级会自动打补丁 | 同文件:CheckPhysicsTable() / UpdataVerSQLScript() | 表缺列/结构差异自动补齐 |
库版本对账 | SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver' | 程序版本 ≠ 库版本才触发升级 |
结论:升级机制是健壮的、幂等的、可跳版本升级的。 你真正需要做的不是"阻止升级",而是控制"什么时候升"——也就是锁定版本。
⚠️ 但自动升级不等于可以随意升。生产环境必须走本文流程。
Ver 号 + Git 提交为唯一标识不要用"上次拉的那版"这种模糊说法。锁版本 = 锁定三样东西:
锁定对象 | 具体锁定 | 记录方式 |
|---|---|---|
后端代码 | Git commit hash / SVN revision | 记录到发布单 |
后端版本号 | Upgrader.cs 里的 Ver 值(如 2026122308) | 记录到发布单 |
前端包 | bpm-vue3 构建产物(dist)的构建时间 + commit | 记录到发布单 |
跨栈一致性:Java 与 .NET 分别有各自的
Ver,必须分别记录、分别升级。 前端dist与后端 API 存在契约,升级后端时必须评估前端是否需同步重建。
开发(dev) ──► 测试(test) ──► 预生产(staging) ──► 生产(prod)
跟随最新 锁定候选版 锁定候选版 锁定正式版任何版本不得跳过 staging 直接上 prod。
建议在项目里维护一份 版本发布单.md(或工单系统),每次发布填写:
## 发布单 vYYYY.MM.DD
- [ ] 后端仓库:Java 版 / .NET 版工程
- [ ] 后端 commit:__________________
- [ ] 后端 Ver :__________________ (Upgrader.cs 中读取)
- [ ] 前端 commit:__________________
- [ ] 前端 dist 构建时间:____________
- [ ] 数据库类型与版本:______________
- [ ] 升级脚本执行结果:______________
- [ ] 回归测试结论:__________________
- [ ] 备份文件位置:__________________# 后端 Ver 号
# Java:在 Java 版源码中查找版本常量
# .NET:引擎流程组件目录/Upgrader.cs
grep -n "public static int Ver" Upgrader.cs
# 库里当前版本
SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver';规则:库版本 ≥ 程序版本 时,升级会被自动跳过;库版本 < 程序版本 时才会打补丁。
顺序不可颠倒:备份 → 停服(或灰度)→ 换代码 → 触发升级 → 验证 → 观察。
备份项 | 说明 |
|---|---|
全库备份 | 升级会改表结构(CheckPhysicsTable 自动补列/改列),必须可回滚 |
应用目录 | 当前运行的程序包(用于回退) |
前端 dist | 当前生产包 |
配置文件 | application.properties / bpm.properties / app.config |
铁律:没有可用的全库备份,不得开始升级。
Java(Java 后端):
# 拉到锁定的 commit(不要直接拉主线)
git checkout <锁定的commit>
mvn -pl bpm-web -am package
# 产出 bpm-web/target/bpm-web-*.jar 替换旧包.NET(.NET 版工程):
git checkout <锁定的commit>
dotnet publish -c Release前端(bpm-vue3):
pnpm install
pnpm build # 产出 dist由 admin 登录后台即自动触发(程序 Ver ≠ 库 Ver 时打补丁)。
用 admin 账号登录 → 系统自动比对版本 → 自动执行补丁脚本 → 更新 Sys_Serial⚠️ SAAS 模式例外:源码中
UpdataVer()对RunModel.SAAS直接返回"info@SAAS模式需要手工升级.",SAAS 需人工升级,不会自动跑。 参见Upgrader.cs中的分支判断。
验证项 | 方法 |
|---|---|
版本号已更新 | 再次执行 SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver',应等于程序 Ver |
核心链路可用 | 发起 → 待办 → 审批 → 结束,全链路跑一遍 |
升级日志无报错 | 检查应用日志 |
历史数据完好 | 抽查历史流程实例、表单、附件可正常打开 |
升级后 24–48 小时为重点观察期,关注:报错日志、定时任务是否正常、消息是否发出、附件上传下载。
源码注释明确了一个机制:
未走升级登录、只是表缺列时,部分功能第一次报错后
CheckPhysicsTable可能自动补列,刷新再试。
处理顺序:
场景 | 动作 |
|---|---|
界面报错但核心流程可用 | 观察 + 记录,不急着回滚 |
核心流程阻断 | 立即回滚(代码 + 数据库) |
数据出现异常写入 | 立即停服回滚,并评估数据修复 |
回滚步骤(与升级相反):
⚠️ 库结构升级可能不可逆(如
ALTER TABLE ... MODIFY MyPK BIGINT)。 所以备份是唯一可靠的退路,这也是第 0 步不可跳过的原因。
历史反馈 | 当前代码状态 | 依据 |
|---|---|---|
附件主键重复 | ✅ 已用防御式兜底修复:主键冲突时自动降级为 GUID 重插 | WorkNode.cs:try { athDB_N.DirectInsert(); } catch { athDB_N.setMyPK(DBAccess.GenerGUID()); athDB_N.Insert(); } |
表单控件报错 | 用 admin 登录触发升级;或刷新让 CheckPhysicsTable 自动补列 | Upgrader.cs |
升级前逐项打勾,任何一项不满足则不升级:
[ ] 已确认目标版本号(Ver)与 commit,并记录到发布单
[ ] 已在 staging 环境完整验证过该版本
[ ] 已完成全库备份,且验证备份可恢复
[ ] 已备份当前程序包 / dist / 配置文件
[ ] 已评估前端是否需同步重建(API 契约是否变化)
[ ] 已确认当前库版本:SELECT IntVal FROM Sys_Serial WHERE CfgKey='Ver'
[ ] 已确认升级窗口(避开业务高峰)
[ ] 已通知相关干系人 / 值班人员
[ ] 非 SAAS 模式(SAAS 需改走人工升级流程)升级后逐项打勾:
[ ] 库版本号已等于程序 Ver 号
[ ] 发起 → 待办 → 审批 → 结束 全链路通过
[ ] 历史流程实例可正常打开(含附件)
[ ] 定时任务正常运行(EnableScheduler=1 时验证 HostURL 可达)
[ ] 日志无异常堆栈
[ ] 观察期(24–48h)无新增报错Q1:能不能一直不升级? 可以。源码设计是"库版本 ≥ 程序版本就跳过"。如果当前版本已够用,不必频繁升级。 但长期不升级会累积补丁,未来跨越大版本时风险更高——建议定期(如每季度)在 staging 演练一次。
Q2:升级会不会丢数据? 正常不会。升级只做结构补丁 + 数据源初始化,不动业务数据。 但 ALTER TABLE 等操作不可逆,所以必须备份。
Q3:为什么官方说"版本控制做得差"? 那是商务语境(商业版走内部 SVN 拿最新代码,服务付费客户),不是工程自评。 工程上的版本控制是:全局 Ver + Sys_Serial 对账 + 幂等补丁 + 自动补列,比多数产品更严谨。
Q4:多实例部署升级要注意什么?
EnableScheduler=1 只允许一台实例开启,否则重复执行。Q5:前端要不要每次跟着后端升? 不一定。当后端 API 契约变化时才需要重建前端。 升级前用"后端 release note / diff API handler"判断,不确定就全量同版本部署(最稳)。
锁定:生产只跑验证过的 Ver + commit,永不跟主线
晋级:dev → test → staging → prod,逐级走
升级:备份 → 换代码 → admin 登录触发 → 验证 → 观察 48h
退路:全库备份是唯一可靠回滚手段(表结构变更不可逆)
例外:SAAS 模式必须人工升级
心态:升级机制本身是幂等、健壮的;要控的是"何时升",不是"能不能升"原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。