阿飞的博客

订单快照设计:一个字段救了未来的自己

article.title

问题起源

用户下单时价格是 99 元,一周后商品涨价到 129 元。此时用户打开订单详情,应该看到哪个价格?

如果订单表只存 sku_id,那么每次查订单都要去商品表取最新价格——结果就是历史订单的价格会随商品涨价而变化。这在财务上完全不可接受。

解决方案

在 order_item 表里冗余三个字段:

字段说明
sku_name下单瞬间的商品名
sku_pic下单瞬间的商品图
price下单瞬间的单价
CREATE TABLE order_item (
  id BIGINT PRIMARY KEY,
  order_id BIGINT NOT NULL,
  sku_id BIGINT NOT NULL,
  sku_name VARCHAR(200) NOT NULL COMMENT 下单时的商品名(快照),
  sku_pic VARCHAR(500) COMMENT 下单时的商品图(快照),
  price INT NOT NULL COMMENT 下单时的单价(快照),
  quantity INT NOT NULL
);

为什么这是对的

数据冗余在这里不是缺点,而是正确设计。

商品名称改了,历史订单不应该跟着改——因为用户当时买的确实是那个名字。同理,价格、图片也一样。

延伸思考

这个思路可以推广到所有「状态会随时间变化,但历史记录必须冻结」的场景:

  • 收货地址:订单要存地址快照,用户改了地址不影响历史订单
  • 优惠券信息:存下单时的券面额
  • 商品规格:存下单时选的规格描述

核心原则:订单是一个契约,契约签订时的条款不能被单方面修改。

标签 JavaMySQL

评论

2
加载中…
无需登录 · 同一 IP 每分钟限 3 条