客服改了地址,发货任务把它改了回去:一次没人报错的覆盖

一条订单,两个写入方,两条都成功的更新,一单发错地址。

晚上九点,客服改收件人,保存成功。同一分钟,发货任务回写状态,也成功。第二天包裹发出------收件人是旧地址。日志里没有一条报错。

根因就一句

两条 UPDATE 都是按主键整行写回。发货任务在九点前就读了这张单,内存里拿着旧快照;写回时把状态和它没碰过的收件人、地址一起写回。谁后提交谁赢,先提交的改动被整体覆盖。

ini 复制代码
UPDATE orders SET receiver='王*', address='新地址',
       status='待发货' WHERE id=1001;   -- 客服:成功
UPDATE orders SET receiver='李*', address='旧地址',
       status='已发货' WHERE id=1001;   -- 任务:也成功

修法三行

表加 version 字段自增,更新带版本条件,看受影响行数:

ini 复制代码
UPDATE orders SET status='已发货', version=version+1
WHERE id=1001 AND version=7;
-- rows == 0 就是冲突,走显式分支,不许静默

版本号随查询下发、随提交回传,前端编辑链路才闭环。

冲突后的纪律(最容易写错的地方)

拿旧数据硬重放 = 换个姿势覆盖。正确动作:重读 → 把本次意图重新应用到最新数据 → 再走一次条件更新,重试设上限。

重试之前必须重读,重试不等于重放。 服务端再进一步:写请求带数据代际,代际落后于当前版本直接拒绝这条在途旧请求。

快速自检

  • 按 WHERE id= 整行写回的 UPDATE 有多少条没带版本条件?
  • rows==0 的分支是显式处理还是被吞了?
  • 缓存里的订单对象带不带 version?旧缓存会让判定失效。

验证动作:测试订单两个终端读同一版本先后提交,后提交方应收到冲突提示,前一个人的改动完好。五分钟搞定。

相关推荐
IT大白鼠1 小时前
渗透测试实战从靶场搭建到渗透流程——第 8 篇 · 服务型靶标(上):MySQL 双版本写文件链
数据库·mysql·渗透测试
piaoyiren1 小时前
Python FTP 服务端项目详细功能文档
网络·数据库·python
少年的范儿2 小时前
Windows 安装 MySQL 8.4 教程(ZIP 解压版):配置 my.ini、初始化数据库与启动服务
数据库·windows·mysql
l1t2 小时前
DeepSeek总结的AI 智能体应该用哪种语言搜索其记忆:SQL 还是 SPARQL?
数据库·人工智能·sql
麦壳饼2 小时前
SonnetDB:PID 调参实战:阶跃响应分析与参数解读
数据库·sonnetdb
猿究院--Cu-Sn合金2 小时前
Spring Boot + DeepSeek 求职 Agent 实践:工具注册、多轮调用与简历 JD 对比
数据库·人工智能·spring boot·后端·deepseek
IvorySQL2 小时前
PostgreSQL 日报|Anonymizer 3.3 修复高危漏洞(10 月 29 日)
数据库·postgresql
geovindu3 小时前
SQL Data Sampling and Approximation Techniques using postgreSQL 18
大数据·数据库·数据仓库·sql·postgresql·数据库开发·数据库架构
zyseo83 小时前
谷歌SEO 关键词研究完整方法论:从种子词到优先级矩阵
数据库·人工智能·矩阵