商品改价接口偶发返回成功但价格没变,日志里 update 的 affected rows 是 0,version 字段还停在旧值,一天出现 17 次。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

UPDATE product SET price = 99, version = version + 1
WHERE id = 1001 AND version = 7;
SELECT ROW_COUNT();

带 version 条件的更新在版本对不上时匹配不到行,影响行数是 0,而代码只判断了 SQL 有没有抛异常。两个请求同时读到同一版本,后写的那个静默失败,用户看到的却是成功。这一点先确认清楚,后面就不用反复试。

「乐观锁版本号」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

具体做法是,update 之后判断 affected rows 为 0 就抛出版本冲突;冲突交给上层重试 重新读取最新版本再提交;version 用数据库自增 不要由应用计算;把影响行数打进日志 方便统计冲突频率。

改完照着核一遍,并发改价时冲突请求返回明确的版本冲突提示 不再出现返回成功但价格没变的情况。

作者 9823189