库存/余额并发写入出现“脏更新”:事务与行锁的正确用法
现象
高并发下出现负库存或重复扣款。
根因
读取后再写入之间被其他事务插入修改,或使用了错误的隔离级别。
修复
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