库存/余额并发写入出现“脏更新”:事务与行锁的正确用法

现象

高并发下出现负库存或重复扣款。

根因

读取后再写入之间被其他事务插入修改,或使用了错误的隔离级别。

修复

from django.db import transaction

def deduct_stock(sku_id, quantity):
    with transaction.atomic():
        sku = SKU.objects.select_for_update().get(id=sku_id)  # 行锁
        if sku.stock < quantity:
            raise ValueError("not enough stock")
        sku.stock -= quantity
        sku.save(update_fields=["stock"])

建议

关键资源使用 select_for_update()

幂等:业务层引入“幂等键”;

设置数据库超时与重试策略。

行锁方案在 gplpal 的订单系统里抗住了秒杀场景。

评论 0