事务的隔离级别
序列化/串行化(Serializable)
**特点:**同时只能有一个事务在执行,如果当前事务未提交,则无法开启一个新的事务。
优点:
隔离程度最高、安全性最好
缺点:
效率太低
可重复读(repeatable)[默认的隔离级别]
用户在同一个事务中执行的select结果是一致的,不受其他事务修改的影响。也就是说,才用户开启事务的时候,创建了一个快照。无论其他数据如何改变,快照的内容是保持不变的
读已提交(read committed)
用户在同一个事务中不同的select结果,受到其他事务修改的影响。其他事务必须提交后,才可以影响到当前的事务
读未提交(read uncommitted)
用户在当前事务中的select受到其他事务修改的影响,即使其他事务没有提交,依然能被当前事务读到。
优点:效率高
缺点:脏读、幻读、不可重复读
查看事务隔离级别
查看全局
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.01 sec)
# MySQL8.0+ 写法
# select @@global.transaction_isolation;
查看当前隔离级别
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
# MySQL8.0+ 写法
# select @@transaction_isolation;
什么是脏读
拿出了数据库不该有的数据
什么是幻读
取出的数据和数据库实际的数据不是一致的
创建订单添加事务
class Goodsview(APIView):
#生成订单
def post(self,request):
#判断登录
user = request.META.get('USER') # 获取到中间件检测完登录,传递过来的用户信息、
if not user:
return Response({
'code': 400,
'msg': '用户未登录'
})
user_id = user['user_id']
addr_id=request.data.get('addr_id')
goods_list=request.data.get('goods_list') #[{'goods_id':1,'num':2},{'goods_id':2,'num':2}]
pay_method=request.data.get('pay_method')
#获取收货地址并验证
addr_info=Addr.objects.filter(id=addr_id,user_id=user_id).first()
if not addr_info:
return Response({
'code':400,
'msg':'收货地址不存在'
})
#获取商品信息并验证
goods_buy=[]
for i in goods_list:
goods_info=Goods.objects.filter(id=i['goods_id']).first()
if not goods_info:
continue
if goods_info.stock<i['num']:
return Response({
'code':400,
'msg':'%s商品库存不足'%goods_info.sku_name
})
goods_buy.append({
'id':i['goods_id'],
'num':i['num'],
'price':goods_info.selling_price
})
from django.db import transaction #导入事务的类
with transaction.atomic(): #开启事务
point=transaction.savepoint() #添加事务的回滚点
try:
#创建订单
order_info=Order.objects.create(
order_id=str(random.randint(100000,999999)),
user_id=user_id,
addr=addr_info,
total_price=0,
total_count=0,
pay_method=pay_method,
pay_status=1,
)
if not goods_buy:
transaction.savepoint_rollback(point)
return Response({
'code': 400,
'msg': '空订单'
})
#创建订单商品
for i in goods_buy:
#创建子订单
OrderGoods.objects.create(
goods_id=i['id'],
count=i['num'],
price=i['price'],
order=order_info,
)
#修改主订单
order_info.total_price+=(i['price']*i['num'])
order_info.total_count+=i['num']
#扣除库存
g_info=Goods.objects.filter(id=i['id']).first()
g_info.stock=i['num']
g_info.save()
order_info.save()
except:
transaction.savepoint_rollback(point) #事务回滚
return Response({
'code': 200,
'msg': '下单失败'
})
#提交事务
transaction.savepoint_commit(point)
#返回下单成功
return Response({
'code':200,
'msg':'下单成功'
})