数据库的事务和django ORM使用数据库事务以及乐观锁并发下单

数据库事务的四大特性(ACID)
  • 原子性: 事务包含的所有操作要么全部成功, 要么全部失败回滚.
  • 一致性: 简单的来说A和B一共有5000元, 不管他们两个之间怎么转账, 他们两的钱相加起来还是5000元
  • 隔离性: 并发的情况下, 每个用户访问同一张, 数据库为每个用户开启的事务, 不能被其它的事务所干扰, 多个事务之间要相互隔离
  • 事务一旦被提交了, 那么数据库中的数据的改变就是永久的, 即使在数据库系统遇到故障的情况下也不会丢失提交的事务
数据库的隔离级别
如果数据库不考虑隔离性的的话会发生什么?
  1. 脏读: 事务在处理过程中读取了另一个未提交的事务中的数据
  2. 不可重复读: 一个事务多次查询相同数据, 结果却不相同
  3. 虚读(幻读): 事务A把表中的所有1改为了2, 此时B又插入了1进表中, 这时A查看修改结果, 发现还有一条没有被修改
  • 不可重复读和脏读的区别是, 脏读是读取了另一个未提交的数据, 而不可重复读是读取了前一个事务提交的数据
  • 幻读和不可重复读都是读取了前一条已经提交的数据, 不同的是不可重复读查询的都是同一项数据, 而幻读针对的是一批数据
mysql的四种隔离级别
  1. 串行化: 避免脏读 不可重复读 幻读发生, 一个事务一个事务的执行
  2. 可重复读: 避免脏读 不可重复读的发生, 无论其他的事务是否修改并提交了数据, 在这个事务中不受其它事务影响(mysql的默认隔离级别)
  3. 读取已提交: 可避免脏读的发生
  4. 读未提交: 最低级别, 什么都无法保证
  • 隔离级别越高, 执行效率就越低
django中ORM使用事务(使用事务有多种方式, 说两种最常用的)
  1. 装饰器: 就django而言, 把整个视图中的所有Mysql数据库的操作都看成一个事务, 范围太大, 不够灵活, 而且无法直接作用于类视图
from django.db import transaction

@transaction.atomic
def viewfunc(request):
  # 这些代码会在一个事务中执行
  ......
  1. 上下文管理器: 可以灵活的有选择的把某些Mysql数据库的操作看做一个事务, 而不用关心视图的类型, 推荐使用
from django.db import transaction

def viewfunc(request):
  # 这部分代码不在事务中,会被 Django 自动提交
  ......

  with transaction.atomic():
      # 这部分代码会在事务中执行
      ......
  1. 事务中的保存点: 可以在事务中创建保存点来记录数据的特定状态, 数据库出现错误时, 可以回滚到保存点的状态
from django.db import transaction

# 创建保存点
save_id = transaction.savepoint()  
# 回滚到保存点
transaction.savepoint_rollback(save_id)
# 提交从保存点到当前状态的所有数据库事务操作
transaction.savepoint_commit(save_id)
乐观锁和悲观锁以及任务队列(用户并发下单的解决办法)
  1. 悲观锁: 和线程中的互斥锁差不多, 就是当一个事务查询某条记录时, 加锁, 不给别人访问
  2. 乐观锁: 乐观锁并不是真实存在的锁, 而是在即将跟新的数据的时候, 再去数据库中查询该条数据还是不是原来查询的值, 如果没变, 则执行跟新操作, 反之不在执行
  3. 任务对列: 将下单的逻辑放到任务队列中, 并将并行转为串行, 所有人排队下单, 比如开启只有一个进程的Celery, 一个订单一个订单的处理.
  • 上面说了数据库的隔离级别, 当要使用乐观锁的时候, 就不能使用可重复读这个默认隔离级别了, 要改为读取已提交, 这样才能保证正常的使用乐观锁.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值