Files
medical-mall/pages/mall/admin/docs/sql/08_data_consistency_boundaries.md

3.9 KiB
Raw Blame History

08 数据一致性边界:数据库保证什么?应用层还需要保证什么?

本节的目的:把“责任边界”讲清楚,避免团队误以为数据库已经覆盖了所有一致性问题。


1. 数据库层已经显式保证的内容(来自脚本)

1.1 约束Constraints保证

  • 枚举合法性:大量使用 CHECK (status IN (...))
    • 例:ml_products.statusml_orders.order_status/payment_status/shipping_status
  • 唯一性
    • order_no UNIQUE
    • coupon_code UNIQUE
    • ml_shopping_cart UNIQUE(user_id, product_id, sku_id)
    • ml_shops.merchant_id UNIQUE(一商家一店)
    • ml_delivery_tasks.order_id UNIQUE(一订单一配送任务)

1.2 触发器保证

  • updated_at 自动维护:避免应用层漏写
  • 默认地址唯一ensure_single_default_address()
  • SKU → SPU 库存汇总update_product_stock()
  • 订单状态副作用complete 脚本)handle_order_status_change() 自动写时间戳,并累计销量

1.3 RLS行级安全保证

  • 用户私有数据仅可访问自己的行(档案/地址/购物车/收藏/浏览/券等)
  • 订单允许买家/卖家访问
  • 商品公开查询仅限上架

2. 数据库层“目前未完全覆盖”的一致性问题(需要显式补齐)

以下并不意味着当前设计不好,而是典型电商系统里必须明确“谁来保证”。

2.1 下单扣库存、防超卖

脚本可见“库存汇总”,但没有看到:

  • 下单时对 ml_product_skus.stock 的原子扣减
  • 订单取消/超时未支付的库存回补
  • 库存冻结(预占)机制

风险:并发下单可能超卖。

建议补齐方案(按复杂度递增):

  • 方案 A最小补齐:提供一个原子扣减函数
    • update ml_product_skus set stock = stock - :qty where id=:sku_id and stock >= :qty;
    • 受影响行数为 1 表示扣减成功,否则失败
  • 方案 B常见电商:引入“冻结库存”
    • SKU 增加 reserved_stock 或独立冻结表
    • 下单冻结、支付确认扣减、取消释放
  • 方案 C审计与对账:引入库存流水
    • 每次扣减/回补记录流水,便于审计

2.2 支付对账与幂等

脚本中订单有 payment_status/paid_amount,但未见:

  • 支付流水表(第三方支付回调存证)
  • 支付回调幂等键
  • 退款流水/退款幂等

建议:补交易流水表(或在应用层引入专门支付子系统)并明确幂等策略。

2.3 优惠券核销一致性

当前有 ml_user_coupons.status/used_at/order_id,但未见:

  • “同一张券只能用一次”的强事务保证(除非应用层做 CAS 更新)
  • 与订单金额计算的强一致校验

建议:

  • 用条件更新核销:where status=1 确保并发只成功一次
  • 关键核销与订单创建在同一事务内

2.4 统计字段回滚

脚本在订单完成时累计 sale_count,但未看到:

  • 退款/取消是否回滚 sale_count

建议:

  • 明确统计字段口径:
    • sale_count 是“累计成交量”还是“累计下单量”
  • 若需可回滚:要补对应触发器/作业,或使用流水聚合。

3. 建议的边界划分(团队共识)

  • 数据库层
    • 基础合法性(约束/唯一性)
    • 关键自动维护字段updated_at、默认地址唯一、库存汇总、SEO 等)
    • 访问控制RLS
  • 应用层
    • 复杂事务(下单扣库存、支付幂等、退款)
    • 业务规则组合(优惠叠加、分摊、拆单、风控)
    • 跨域协调(订阅与订单的统一计费/对账)

4. 推荐补充的“最小一致性清单”(可用于评审)

  • 下单扣减库存是否原子?
  • 未支付关闭订单是否回补库存?
  • 支付回调是否幂等?
  • 退款回调是否幂等?
  • 优惠券核销是否并发安全?
  • 统计字段口径是否明确、是否需要回滚?