切换日光/暗黑模式
061. Version 字段、更新策略与锁选择
学习目标
这一节讨论乐观锁里的 version 字段是否要做成通用字段,并比较几种更新策略。
学完后,你应该能理解:
- version 字段为什么不一定适合做成标准字段;
- 按需更新和全量更新有什么区别;
- 全量更新为什么更需要互斥控制;
- 悲观锁和乐观锁的取舍;
- 为什么后端代码看起来简单但责任更重。
version 不一定是标准字段
乐观锁通常需要 version 字段。
但它不一定要放进所有表的基础字段里。
原因是项目里很多更新是按需更新。
只有真正需要并发控制的表,才需要 version。
例如库存、积分、金额、项目已花费金额等字段更新,才更适合加 version。
普通信息表不一定需要。
按需更新
按需更新是指:前端只提交被修改的字段。
例如只改备注:
json
{
"id": "001",
"remark": "new remark"
}后端生成 SQL 时也只更新 remark。
没有提交的字段,不会被写入 SQL。
这样 A 用户改备注、B 用户改标题时,两个修改互不覆盖。
全量更新
全量更新是指:更新时把整条记录的所有字段都提交上来。
它的风险是:用户没有修改的旧字段,也会被一起写回数据库。
例如 A 改了字段一,B 改了字段二。
如果两边都是全量更新,后提交的人可能把先提交的人改动覆盖掉。
这时就很需要 version 做互斥控制。
JS/Python 的优势
JS 和 Python 都很容易遍历对象或字典。
后端可以根据请求体里实际出现的字段生成更新语句。
这让按需更新更自然。
某些后端栈如果默认生成全量更新,要实现按需更新会麻烦一些。
所以不同语言和 ORM 的写法,会影响并发控制策略。
冲突字段如何处理
按需更新不是没有冲突。
如果 A 和 B 同时修改同一个字段,最后仍然只能保留一个结果。
但这类冲突通常可以接受:最后提交的人覆盖前一个人。
真正危险的是金额、库存、计数器这类需要“基于旧值计算新值”的字段。
这类字段不能简单最后写入为准。
悲观锁回顾
悲观锁是在操作数据前先锁住数据。
它的特点是:
- 数据安全性强;
- 实现简单;
- 数据库阻塞明显;
- 索引失效时可能锁表;
- 适合低并发、高一致性场景。
如果业务像银行核心账务一样,写操作不算高频,但正确性极高,悲观锁仍然有价值。
乐观锁回顾
乐观锁不在读取时加锁。
它在更新时判断 version 有没有变化。
如果变化了,就说明数据被别人改过,需要重新读取和重试。
它的特点是:
- 并发性能更好;
- 数据库阻塞更少;
- 代码更复杂;
- 后端会承担重试压力;
- 适合冲突概率可控的场景。
压力放在哪里
悲观锁把等待压力放在数据库。
用户排队时,数据库锁住记录,其他请求等待。
乐观锁把等待压力放在后端。
后端先执行业务逻辑,更新失败后再重试。
数据库压力小一些,但后端 CPU、内存和请求生命周期会增加。
后端责任更重
前端 bug 很多时候是展示错误或参数错误。
后端 bug 可能直接影响金额、库存、优惠券、订单、审批状态。
所以后端逻辑看起来不一定更复杂,但责任更大。
AI 生成代码后,开发者仍然要判断并发、安全、事务和异常边界。
不能只看“本地跑通”。
这一节的重点
这一节把 version 字段和锁策略放回业务场景里看。
你需要记住:
- version 不必变成所有表的标准字段;
- 按需更新能减少字段覆盖;
- 全量更新更依赖互斥控制;
- 金额、库存、计数器必须考虑并发;
- 悲观锁压数据库,乐观锁压后端;
- 让 AI 写代码前,你要先知道该选哪类方案。