数据库悲观锁的实现

悲观锁

是一种在并发控制中常用的策略,主要用于防止数据在并发访问时发生冲突
不允许别人访问它 处于一个悲观的状态

SELECT … **FOR UPDATE:**在SQL语句中使用SELECT … FOR UPDATE可以锁定查询结果集中的数据行,确保其他事务无法对这些行进行修改(包括INSERT、UPDATE和DELETE操作)。直到当前事务提交或回滚,锁才会被释放。

优点:

能够确保数据的一致性和完整性,避免并发冲突。
实现相对简单,不需要复杂的版本控制机制。

缺点:

性能开销大,特别是在高并发场景下可能影响系统性能。
容易产生死锁问题,如果锁的管理不当可能会导致系统无法继续运行。
可能导致资源浪费,如果事务长时间持有锁而不释放,其他事务将无法访问被锁定的数据。

// Sell 扣减库存 悲观锁实现
func (c *Server) Sell(ctx context.Context, in *proto.SellInfo) (*proto.Empty, error) {
	//开启本地事务
	//并发情况下出现超卖的问题 要确保他的一致性 一起成功或者一起失败
	tx := global.Db.Begin()
	if tx.Error != nil {
		return nil, status.Errorf(codes.Internal, "事务开启失败")
	}
	for _, info := range in.GoodsInfo {
		//定义一个库存存放的结构体
		//查询是否有这个库存
		var inv model.Inventory
		//悲观锁
		result := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where(&model.Inventory{GoodsId: info.GoodsId}).First(&inv)
		if result.RowsAffected == 0 || result.Error != nil {
			tx.Rollback() //事务回滚
			return nil, status.Errorf(codes.Internal, "库存详情查询失败")
		}

		if inv.Number < info.Num {
			tx.Rollback() //事务回滚
			return nil, status.Errorf(codes.Internal, "库存不足")
		}

		inv.Number -= info.Num

		res := tx.Save(&inv)
		if res.Error != nil {
			tx.Rollback() //事务回滚
			return nil, status.Errorf(codes.Internal, "设置库存失败")
		}
	}
	tx.Commit()
	return &proto.Empty{}, nil
}

在gorm中如何实现悲观锁

Clauses(clause.Locking{Strength: “UPDATE”})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值