两名管理员先后保存渠道配置,怎样阻止旧页面覆盖新修改
让保存语句同时匹配记录ID与读取时的版本号。第一份修改成功后版本递增,旧页面再次保存影响零行,服务端应返回冲突信息,要求用户比较新旧内容后重新提交。
复现最后写入覆盖
问题通常发生在两人都打开旧页面以后:甲先保存新路由,乙稍后提交旧页面里修改的超时,整个对象被写回,甲的路由随之消失。只按ID执行UPDATE无法识别乙的编辑基础已经过期,页面有没有显示保存成功也不能说明并发修改得到保护。
定义实体版本与提交条件
样本把版本固定为7,两份编辑都基于这一版本。第一份条件更新影响一行并升到8;第二份仍要求version=7,所以影响零行。最终正文保持first、版本保持8。附件中的409只是演示接口如何表达这种冲突,数据库本身不会替管理API自动生成HTTP响应。
保存接口可以把UPDATE影响行数作为数据库竞争结果,再结合授权范围判断返回内容。版本号应随同需要保护的配置字段一起递增,不能只在页面刷新时改。若配置允许删除后重建,还要考虑新对象是否可能复用旧ID与旧版本,避免旧编辑误匹配到另一代记录。
核心表达式(完整建表与输入见附件):
UPDATE channels SET body=?, version=version+1
WHERE id=? AND version=?;
说明版本锁不涵盖跨实体事务
零行还可能来自记录已删除或授权条件不满足,接口不要把所有零行都公开成“版本冲突”,以免泄露别的租户记录。真正的合并应比较字段与业务约束;无条件拉取最新版本再自动重试旧整对象,等于绕过了原本想保护的更新边界。
适用范围:只演示数据库条件更新;HTTP409是样例管理接口协议,不冒充现成产品原生行为。
配套样本与复核入口
- run.py:独立运行程序,包含合成输入、操作和正反例断言。
- case.json:输入说明、预期任务与适用范围,便于保存和交接。
- observed.json:本次实际执行输出;临时路径、进程号和计时可能随运行变化。
run.py会顺序提交两份基于版本7的编辑。first_rows应为1,stale_rows应为0,final应保留first与8。可以把第二份编辑的正文改成其他字符串,结果仍不能覆盖第一份。接入真实管理接口时,建议将记录ID、原版本与冲突提示一起记录,方便用户知道需要重新加载哪一份内容,而不是仅弹一个无法理解的失败。
Python3.8以上及标准库;使用Python自带SQLite。程序不读取现有网关数据库,全部样本写入内存或新建临时目录,执行完自动清理;没有任何模型API调用。
python -B run.py
阅读输出时,先按case.json中的任务逐项核对网关配置乐观锁版本冲突,再与observed.json比较。非零退出表示依赖或断言需要处理,应保留实际错误。
一手依据1(UPDATE用WHERE限定修改行;版本条件和冲突响应是本文应用协议。);一手依据2(占位符绑定参数;rowcount、连接超时及progress_handler等接口按相应小节使用。)。
继续阅读:渠道配置改成功却没留下审计记录,怎样把两次写入放进同一事务;两个网关任务同时累计用量为何少一笔,怎样用数据库原子累加替代先读后写;限流规则热更新时,怎样避免同一请求混读两个配置版本。
不想自己搭网关、自己维护渠道?
力达云是托管的 OpenAI / Anthropic 双格式端点,一期提供 DeepSeek,注册送 ¥5 额度。