购物车结算是电商系统的核心功能之一,使用mysql实现该功能需要从数据库表结构设计、业务逻辑处理、数据一致性保障等多个维度入手,确保结算过程准确、稳定。

核心数据库表结构设计
实现购物车结算需要至少设计四张核心表,分别存储用户、商品、购物车、订单相关信息,表结构如下:
用户表 user
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(11) unsigned | 用户ID,主键自增 |
| username | varchar(50) | 用户名 |
商品表 product
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(11) unsigned | 商品ID,主键自增 |
| name | varchar(100) | 商品名称 |
| price | decimal(10,2) | 商品单价 |
| stock | int(11) unsigned | 商品库存 |
购物车表 cart
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(11) unsigned | 购物车记录ID,主键自增 |
| user_id | int(11) unsigned | 用户ID,关联user表id |
| product_id | int(11) unsigned | 商品ID,关联product表id |
| quantity | int(11) unsigned | 商品购买数量 |
| is_selected | tinyint(1) | 是否选中结算,1是0否 |
订单表 order_info
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(11) unsigned | 订单ID,主键自增 |
| user_id | int(11) unsigned | 用户ID,关联user表id |
| total_amount | decimal(10,2) | 订单总金额 |
| status | tinyint(1) | 订单状态,1待支付2已支付3已取消 |
| create_time | datetime | 订单创建时间 |
订单商品表 order_product
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(11) unsigned | 记录ID,主键自增 |
| order_id | int(11) unsigned | 订单ID,关联order_info表id |
| product_id | int(11) unsigned | 商品ID,关联product表id |
| quantity | int(11) unsigned | 商品购买数量 |
| price | decimal(10,2) | 商品结算单价 |
购物车结算核心流程
完整的购物车结算流程主要包含以下步骤:
- 查询用户选中的购物车商品信息,校验商品是否存在、库存是否充足
- 计算订单总金额,生成订单主记录
- 批量插入订单商品关联记录
- 扣减对应商品的库存
- 清空用户购物车中已结算的商品记录
以上步骤必须放在同一个事务中执行,避免部分操作成功部分失败导致的数据不一致问题。
核心SQL实现示例
查询选中购物车商品并校验库存
首先查询用户选中的购物车商品,同时关联商品表获取商品最新价格和库存,校验库存是否足够:
-- 查询用户ID为1的选中购物车商品,同时校验库存
SELECT
c.product_id,
c.quantity AS cart_quantity,
p.price,
p.stock,
p.name
FROM cart c
JOIN product p ON c.product_id = p.id
WHERE c.user_id = 1
AND c.is_selected = 1
AND p.stock >= c.quantity;
如果查询结果为空,说明存在库存不足或者商品不存在的情况,需要终止结算流程并提示用户。
事务内执行结算操作
使用mysql的事务机制,将订单生成、库存扣减、购物车清空操作放在同一个事务中:
-- 开启事务 START TRANSACTION; -- 1. 计算订单总金额,插入订单主表,假设查询到的商品总金额为199.8 INSERT INTO order_info (user_id, total_amount, status, create_time) VALUES (1, 199.8, 1, NOW()); -- 获取刚生成的订单ID SET @order_id = LAST_INSERT_ID(); -- 2. 插入订单商品关联记录,假设购物车选中的是商品ID为1和2的商品,数量分别为1和2 INSERT INTO order_product (order_id, product_id, quantity, price) VALUES (@order_id, 1, 1, 99.9), (@order_id, 2, 2, 49.95); -- 3. 扣减商品库存 UPDATE product SET stock = stock - 1 WHERE id = 1; UPDATE product SET stock = stock - 2 WHERE id = 2; -- 4. 清空用户购物车中已选中的商品 DELETE FROM cart WHERE user_id = 1 AND is_selected = 1; -- 所有操作执行成功,提交事务 COMMIT;
如果执行过程中出现异常,比如库存扣减失败、订单插入失败,需要执行回滚操作,保证数据回到事务开始前的状态:
-- 出现异常时执行回滚 ROLLBACK;
常见问题与优化方案
库存超卖问题
高并发场景下可能出现多个用户同时结算同一商品,导致库存扣减为负的情况,可以在更新库存时增加库存校验条件:
-- 更新库存时校验当前库存大于等于要扣减的数量 UPDATE product SET stock = stock - 2 WHERE id = 2 AND stock >= 2; -- 判断受影响行数,如果为0说明库存不足,需要回滚事务
结算金额一致性
结算时商品单价要使用商品表的最新价格,而不是购物车存储的历史价格,避免商家改价后结算金额出现偏差,上述查询购物车商品的SQL已经关联了商品表获取最新价格,可以保证金额准确。
购物车数据清理
结算完成后只删除已选中的购物车记录,未选中的商品仍然保留在购物车中,符合用户使用习惯,上述DELETE语句已经通过is_selected = 1条件过滤了未选中的商品。