当前位置: 首页 > news >正文

django中实现事务/django实现悲观锁乐观锁案例

django中实现事务的几种方式

# 1 全局开启事务---> 全局开启事务,绑定的是http请求响应整个过程DATABASES = {'default': {#全局开启事务,绑定的是http请求响应整个过程'ATOMIC_REQUESTS': True, }}from django.db import transaction# 局部禁用事务@transaction.non_atomic_requestsdef seckill(request):return HttpResponse('秒杀成功')# 2 一个视图函数在一个事物中# fbv开启from django.db import transaction@transaction.atomicdef seckill(request):return HttpResponse('秒杀成功')# cbv开启from django.db import transactionfrom rest_framework.views import APIViewclass SeckillAPIView(APIView):@transaction.atomicdef post(self, request):pass# 3 局部使用事务
from django.db import transaction
def seckill(request):with transaction.atomic():pass  # 都在一个事物中return HttpResponse('秒杀成功')

事物的回滚和保存点


# 1 普通事务操作(手动操作)
transaction.atomic()  # 开启事务
transaction.commit()  # 提交事务
transaction.rollback() # 回滚事务# 2 可以使用上下文管理器来控制(自动操作)
with transaction.atomic():  # 自动提交和回滚# 3 保存点-开启事务干了点事设置保存点1干了点事设置一个保存点2干了点事回滚到干完第二个事,回滚到保存点2'''
在事务操作中,我们还会经常显式地设置保存点(savepoint)
一旦发生异常或错误,我们使用savepoint_rollback方法让程序回滚到指定的保存点
如果没有问题,就使用savepoint_commit方法提交事务
'''from .models import Book
from django.db import transaction
def seckill(request):with transaction.atomic():# 设置回滚点,一定要开启事务sid = transaction.savepoint()print(sid)try:book = Book.objects.get(pk=1)book.name = '红楼梦'book.save()except Exception as e:# 如发生异常,回滚到指定地方transaction.savepoint_rollback(sid)print('出异常了,回滚')# 如果没有异常,显式地提交一次事务transaction.savepoint_commit(sid)return HttpResponse('秒杀成功')
transaction.atomic()  # 开启事务
sid = transaction.savepoint() # 设置保存点
transaction.savepoint_rollback(sid) # 回滚到保存点
transaction.savepoint_commit(sid) #提交保存点

事务提交后,执行某个回调函数

# 有的时候我们希望当前事务提交后立即执行额外的任务,比如客户下订单后立即邮件通知卖家
###### 案例一##################
def send_email():print('发送邮件给卖家了')
def seckill(request):with transaction.atomic():# 设置回滚点,一定要开启事务sid = transaction.savepoint()print(sid)try:book = Book.objects.get(pk=1)book.count = book.count-1book.save()except Exception as e:# 如发生异常,回滚到指定地方transaction.savepoint_rollback(sid)else:transaction.savepoint_commit(sid)#transaction.on_commit(send_email)transaction.on_commit(lambda: send_sms.delay('1898288322'))return HttpResponse('秒杀成功')##### 案例二:celery中使用###
transaction.on_commit(lambda: send_sms.delay('1898288322'))

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数据库

原生mysql悲观锁

begin; # 开启事务select * from goods where id = 1 for update;  # 行锁# order表中加数据update goods set stock = stock - 1 where id = 1; # 更新commit; #提交事务

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-1book.save()transaction.savepoint_commit(sid)  # 提交,释放行锁return HttpResponse('秒杀成功')else:transaction.savepoint_rollback(sid) #回滚,释放行锁return HttpResponse('库存不足,秒杀失败')

乐观锁秒杀--》库存还有,有的人就没成功

# 2 乐观锁秒杀--普通版
@transaction.atomic
def seckill(request):# 锁住查询到的book对象,直到事务结束sid = transaction.savepoint()book = Book.objects.filter(pk=1).first()  # 没加锁count = book.countprint('现在的库存为:%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('库存不足,秒杀失败')

http://www.lryc.cn/news/124865.html

相关文章:

  • 自动驾驶技术:改变交通出行的未来
  • 5.利用matlab完成 符号矩阵的转置和 符号方阵的幂运算(matlab程序)
  • 为什么要自动化Web测试?
  • Spark_RDD的容错机制_数据丢失恢复
  • VB+SQL期刊信息管理系统设计与实现
  • 如何在iPhone手机上修改手机定位和模拟导航?
  • Linux 当fork在for循环中的问题
  • 推断统计中非参数检验之卡方检验、列联表分析和游程检验
  • AI社交来了,百度、Soul“双向奔赴”
  • 【【verilog 典型电路设计之加法器树乘法器】】
  • 选择最适合自己的NIO, 一探流技术
  • 智能家居(3)---socket网络控制线程封装
  • ubuntu 安装 emscripten 时 install latest 安装报错问题
  • concrt140.dll丢失怎么恢复?教你5种修复方法
  • 【Vue-Router】路由入门
  • 蓝牙耳机运动耳机哪个好、好用的运动蓝牙耳机推荐
  • 大数据面试题:Kafka的ISR机制
  • Windows:解决MySQL登录ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using passwor=YES)问题
  • springboot整合kafka多数据源
  • 基于CentOS 7 配置nginx负载均衡
  • WordToPDF2.java
  • k8s服务注册发现
  • IK分词器升级,MySQL热更新助一臂之力
  • 泛微 E-Office文件上传漏洞复现
  • bug的生命周期
  • mysql分库分表相关
  • 云原生k8s---资源限制、探针
  • html2canvas生成图片地址Base64格式转成blob在转成file(二进制)可正常发送(保姆教程,复制粘贴可用)
  • 将Linux上的cpolar内网穿透配置为开机自启动——“cpolar内网穿透”
  • 微信小程序data-item设置获取不到数据的问题