django实现悲观锁乐观锁的项目实践
作者:淘淘桃
在Django中,我们可以通过实现悲观锁和乐观锁来保证数据的安全性,本文就来介绍一下django实现悲观锁乐观锁的项目实践,感兴趣的可以了解一下
前期准备
# 线上卖图书 -图书表 图书名字,图书价格,库存字段 -订单表: 订单id,订单名字 # 表准备 class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField() # count = models.SmallIntegerField(verbose_name='库存') class Order(models.Model): order_id = models.CharField(max_length=64) order_name = models.CharField(max_length=32) # 使用mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'lqz', 'HOST': '127.0.0.1', 'PORT': '3306', 'USER': 'lqz', 'PASSWORD': '123', } } # 创建lqz数据库
1.原生mysql悲观锁
begin; # 开启事务 select * from goods where id = 1 for update; # 行锁 # order表中加数据 update goods set stock = stock - 1 where id = 1; # 更新 commit; #提交事务
2.orm实现上述(悲观锁)
#1 使用悲观锁实现下单 @transaction.atomic # 整个过程在一个事物中---》改两个表:book表减库存,订单表生成记录 def seckill(request): # 锁住查询到的book对象,直到事务结束 sid = transaction.savepoint() # 保存点 # 悲观锁: select_for_update() # 加锁了--》行锁还是表锁? 分情况,都有可能 # book = Book.objects.select_for_update().filter(pk=1).first() # 加悲观锁,行锁,锁住当前行 if book.count > 0: print('库存可以,下单') # 订单表插入一条 Order.objects.create(order_id=str(datetime.datetime.now()), order_name='测试订单') # 库存-1,扣减的时候,判断库存是不是上面查出来的库存,如果不是,就回滚 time.sleep(random.randint(1, 4)) # 模拟延迟 book.count=book.count-1 book.save() transaction.savepoint_commit(sid) # 提交,释放行锁 return HttpResponse('秒杀成功') else: transaction.savepoint_rollback(sid) #回滚,释放行锁 return HttpResponse('库存不足,秒杀失败')
3 乐观锁秒杀--》库存还有,有的人就没成功
# 2 乐观锁秒杀--普通版 @transaction.atomic def seckill(request): # 锁住查询到的book对象,直到事务结束 sid = transaction.savepoint() book = Book.objects.filter(pk=1).first() # 没加锁 count = book.count print('现在的库存为:%s' % count) if book.count > 0: print('库存可以,下单') Order.objects.create(order_id=str(datetime.datetime.now()), order_name='测试订单-乐观锁') # 库存-1,扣减的时候,判断库存是不是上面查出来的库存,如果不是,就回滚 # time.sleep(random.randint(1, 4)) # 模拟延迟 res = Book.objects.filter(pk=1, count=count).update(count=count - 1) if res >= 1: # 表示修改成功 transaction.savepoint_commit(sid) return HttpResponse('秒杀成功') else: # 修改不成功,回滚 transaction.savepoint_rollback(sid) return HttpResponse('被别人改了,回滚,秒杀失败') else: transaction.savepoint_rollback(sid) return HttpResponse('库存不足,秒杀失败')
到此这篇关于django实现悲观锁乐观锁的项目实践的文章就介绍到这了,更多相关django 悲观锁乐观锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!