并发编辑防护:多人协作同一模型而不互相覆盖
Rexfin 如何阻止两个人同时编辑同一份计划时悄悄覆盖彼此的工作,以及这种情况几乎发生的那一刻,屏幕上会显示什么。
作者 The Rexfin team
两个人打开同一份人员编制计划。一人调整了某个招聘日期,另一人在同一行调整了薪资区间,两人在相隔几秒内先后点击保存。如果没有防护机制,后一个保存操作就会直接覆盖前一个,第一处修改就此消失,没有报错,没有提示,界面上也没有任何痕迹说明它曾经存在过。这正是 Rexfin 的并发编辑防护要杜绝的故障模式。
普通保存操作的问题
一个只是简单覆写已存储内容的保存操作,也就是一次朴素的 upsert,在只有一个编辑者时运作良好。一旦有多个编辑者,它就无法察觉这一行数据在被加载和被保存之间已经在别处发生了变化。第二次写入本身并没有错;它只是遗漏了第一个人的修改,而且看起来和一次正常、成功的保存一模一样。Rexfin 团队正是在人员编制名册上发现并修复了这个模式:两名编辑者同时处理同一份计划时,可以通过保存接口互相覆盖对方的修改,且不留下任何痕迹。
Rexfin 如何捕捉这种情况
修复方案是乐观锁:每一条计划记录都携带一个版本号。加载计划时,你也会悄悄获取当时所看到的那个版本号。保存时,只有当服务器上的版本号仍与你最后看到的版本号一致,这次保存才被允许成功。如果其他人在此期间已经保存过,版本号已经发生了变化,你的保存就会被判定为冲突并被拒绝,而不是直接覆盖上去。
真正重要的是接下来界面会发生什么。被拒绝的保存不会悄无声息地失败,也不会被静默地重试成部分成功。它会显示一条清晰、很难被忽略的提示:其他人在此期间已经保存过这份内容,你需要重新加载后才能继续。这是一个有意为之的选择:一次打断,总比一次看似成功、实则悄悄丢弃了他人修改的保存要好。如果某条记录的版本数据最终陷入不一致状态,系统的设计是让它能够自我修复,而不是卡死不动:它会以计划已清空但真实版本号保留的方式加载,这样下一次保存就能修复它,而不会陷入永久性的冲突循环。
不止一处表单
在人员编制计划上验证了这套模式之后,团队在产品范围内更广泛地排查了同一类保存接口,发现合规设置中也存在第二个类似的更新丢失案例:一次保存操作先读取现有记录,合并进一处修改,再把整条记录整体写回。这属于同一种静默覆盖风险,只是换了个名字出现,如今它已被限定为只写入实际发生变化的那个具体字段,而不是整条记录。
同一轮审查中还发现了几个相关的边界情况。两个人几乎同时创建同名的新版本,原本可能发生名称冲突;创建操作现在会以追加后缀的方式重试,让两次保存都能成功落地,而不是让其中一次直接失败。把某个部门移动到不同的上级部门下时,原本存在一个狭窄的时间窗口,两次同时进行的移动操作可能组合成一个真正的循环,即某部门通过层层关系最终又向自己汇报;这项操作现在是一个单一的、要么全部成功要么全部不生效的事务。还有一个更隐蔽的情况:一条全新记录的首次保存过去被赋予了与“这里还什么都没有”相同的版本标记,这意味着创建计划后的第一次修改可能像一次不受保护的保存那样被覆盖。新记录如今从一个不会与空记录混淆的版本号开始计数。
它在工作区中处于什么位置
这项防护机制在 Rexfin 中财务团队每天接触的部分之下静默运行。它使得团队工作区真正能够让多名编辑者同时使用,而不是变成一场互相踩踏彼此工作的邀请。它与评论和审核流程相互配合,讨论在编辑旁边发生,而不是在另一个独立工具里;也与版本管理与审计轨迹相互配合,一旦某次冲突促使你去核实,那里正是你能看到具体改动内容与时间的地方。结合 Rexfin 产品导览中的其余部分,这些共同让一份共享模型真正成为团队可以同时协作的对象,而不只是一份轮流触碰的文件。