事务

概念

Transaction

事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)

一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成

事务只和DML语句 ( 数据库操作语句 ) 有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同

特性

▧ 原子性(A)  事务是最小单位,不可再分

▧ 一致性(C)  事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败

▧ 隔离性(I)  事务A和事务B之间具有隔离性

▧ 持久性(D)  是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中)

行为

▧ 开启事务  Start Transaction

▧ 事务结束  End Transaction

▧ 提交事务  Commit Transaction

▧ 回滚事务  Rollback Transaction

标志

开启标志

任何一条DML语句(insert、update、delete)执行,标志事务的开启

结束标志

▧ 提交  成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步

▧ 回滚  失败的结束,将所有的DML语句操作历史记录全部清空

代码库

Django 自带的代码库

from django.db import transaction

使用

方式一, 直接使用将一段操作设置为事务

with transaction.atomic():
...

方式二, 装饰器方式

@transaction.atomic
def foo():
....

悲观锁

概念

总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等)

当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁

保证同一时刻只有一个线程能操作数据,其他线程则会被 block

运用场景

▧ 无脏读  上锁数据保证一致, 因此无脏读, 对脏读不允许的环境悲观锁可以胜任 

▧ 无并行  悲观锁对事务成功性可以保证, 但是会对数据加锁导致无法实现数据的并行处理.

▧ 事务成功率高  上锁保证一次成功, 因此在对数据处理的成功率要求较高的时候更适合悲观锁.

▧ 开销大  悲观锁的上锁解锁是有开销的, 如果超大的并发量这个开销就不容小视, 因此不适合在高并发环境中使用悲观锁 

▧ 一次性完成  如果乐观锁多次尝试的代价比较大,也建议使用悲观锁, 悲观锁保证一次成功

实例

from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
from django.db import transaction
from 应用名.models import 模型类名 # 类视图 (并发,悲观锁)
class MyView(View): @transaction.atomic
def post(self, request):
# select * from 表名 where id=1 for update;
# for update 就表示锁,只有获取到锁才会执行查询,否则阻塞等待。
obj = 模型类名.objects.select_for_update().get(id=1) # 等事务提交后,会自动释放锁。 return HttpResponse('ok')

乐观锁

概念

总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁

但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。

如果发现数据被改了. 就进行事务回滚取消之前的操作

运用场景

▧ 脏读  乐观锁不涉及到上锁的处理, 因此在数据并行需求的时候是更适合乐观锁,当然会产生脏读, 不过用回滚取消掉了.

▧ 高并发  相比起悲观锁的开销, 乐观锁也是比悲观锁更适合于高并发场景

▧ 事务成功率低  乐观锁不能保证每次事务的成功, 是使用回滚方式来保证数据一致性, 因此会导致事务成功率很低.

▧ 读多写少  乐观锁适用于读多写少的应用场景,这样可以提高并发粒度

▧ 开销小  可能会导致很多次的回滚都不能拿到正确的处理回应, 因此如果对成功性要求低,而且每次开销小比较适合乐观锁

实例

from django.shortcuts import render
from django.http import JsonResponse
from django.views.generic import View
from django.db import transaction
from 应用名.models import GoodsSKU # 类视图 (并发,乐观锁)
class MyView(View): @transaction.atomic
def post(self, request):
'''订单创建'''
count = 3 # 订购3件商品 # 设置事务保存点
s1 = transaction.savepoint() # 乐观锁,最多尝试5次
for i in range(5):
# 查询商品的信息(库存)
try:
sku = GoodsSKU.objects.get(id=1)
except:
# 商品不存在
transaction.savepoint_rollback(s1)
return JsonResponse({'res': 1, 'errmsg': '商品不存在'}) # 判断商品的库存
if count > sku.stock:
transaction.savepoint_rollback(s1)
return JsonResponse({'res': 2, 'errmsg': '商品库存不足'}) # 更新商品的库存和销量
orgin_stock = sku.stock # 原库存 (数据库隔离级别必须是Read Committed;如果是Repeatable Read,那么多次尝试读取的原库存都是一样的,读不到其他线程提交更新后的数据。)
new_stock = orgin_stock - count # 更新后的库存
new_sales = sku.sales + count # 更新后的销量 # update 商品表 set stock=new_stock, sales=new_sales where id=1 and stock = orgin_stock
# 通过where子句中的条件判断库存是否进行了修改。(并发,乐观锁)
# 返回受影响的行数
res = GoodsSKU.objects.filter(id=1, stock=orgin_stock).update(stock=new_stock, sales=new_sales)
if res == 0: # 如果修改失败
if i == 4:
# 如果尝试5次都失败
transaction.savepoint_rollback(s1)
return JsonResponse({'res': 3, 'errmsg': '下单失败'})
continue # 再次尝试 # 否则更新成功
# 跳出尝试循环
break # 提交事务
transaction.savepoint_commit(s1) # 返回应答
return JsonResponse({'res': 4, 'message': '创建成功'})

Django - ORM - 事务, 乐观锁, 悲观锁的更多相关文章

  1. Java并发 行级锁/字段锁/表级锁 乐观锁/悲观锁 共享锁/排他锁 死锁

    原文地址:https://my.oschina.net/oosc/blog/1620279 前言 锁是防止在两个事务操作同一个数据源(表或行)时交互破坏数据的一种机制. 数据库采用封锁技术保证并发操作 ...

  2. 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观 ...

  3. 乐观锁悲观锁对应的JAVA代码和数据库

    乐观锁悲观锁是一种思想.可以用在很多方面. 比如数据库方面.悲观锁就是for update乐观锁就是 version字段 JDK方面:悲观锁就是sync乐观锁就是原子类(内部使用CAS实现) 本质来说 ...

  4. AtomicInteger如何保证线程安全以及乐观锁/悲观锁的概念

    众所周知,JDK提供了AtomicInteger保证对数字的操作是线程安全的,线程安全我首先想到了synchronized和Lock,但是这种方式又有一个名字,叫做互斥锁,一次只能有一个持有锁的线程进 ...

  5. Java中的锁-悲观锁、乐观锁,公平锁、非公平锁,互斥锁、读写锁

    总览图 如果文中内容有错误,欢迎指出,谢谢. 悲观锁.乐观锁 悲观锁.乐观锁使用场景是针对数据库操作来说的,是一种锁机制. 悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数 ...

  6. Mysql锁机制--乐观锁 & 悲观锁

    Mysql 系列文章主页 =============== 从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁.所以本文将对锁(乐观锁.悲观锁)进行分析. 第一部分 悲观锁 ...

  7. MySQL 乐观锁 悲观锁 共享锁 排他锁

    乐观锁 乐观锁是逻辑概念上的锁,不是数据库自带的,需要我们自己去实现.乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,在操作数据时,并不进行任何其他的特殊处理(也就是不加锁 ...

  8. 乐观锁&悲观锁

    悲观&乐观,只是对数据加锁的时机与粒度. 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这 ...

  9. Java并发之乐观锁悲观锁

    定义 乐观锁和悲观锁这两种锁机制,是在多用户环境并发控制的两种所机制. 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作.[1]常见实现如独占锁.乐观锁:假设不会发生并发冲突,只在提交操作 ...

随机推荐

  1. pycharm2017.3版本永久激活

    1.下载破解文件 链接:https://pan.baidu.com/s/1nwI278l 密码:j3gt 2.修改检测文件 ,在文件后缀是vmoptions的 文件中加入(注意是文件中,不是文件后缀上 ...

  2. PAT Advanced 1073 Scientific Notation (20 分)

    Scientific notation is the way that scientists easily handle very large numbers or very small number ...

  3. 计算广告(4)----搜索广告召回(也叫match、触发)

    一.搜索广告形态 1.特征工程 特征主要有用户画像(user profile).用户行为(user behavior).广告(ad)和上下文(context)四部分组成,如下所示: 2.平台算法主要分 ...

  4. ASP.NET MVC QQ互联接入

    ASP.NET MVC QQ Connect 介绍 ASP.NET MVC QQ互联接入Demo. 项目地址:https://gitee.com/Liu_Cabbage/ASP.NET-MVC-QQ- ...

  5. 对Ajax的一些理解

    前言 在学习js的过程,我个人对于Ajax这项技术有着很深的印象,大概是因为它在我们网页开发过程中常见的交互里所发挥的作用太过于关键了吧,所以我想在这里好好地谈一些自己对它的理解. 概念理解 Ajax ...

  6. BZOJ 3901 棋盘游戏 (找结论+枚举+贪心)

    题面 略 BZOJ 传送门 分析 具体分析见 dalao博客 妙就妙在当i<x,j<xi<x,j<xi<x,j<x时,(i,j)(i,j)(i,j) ^ (i,x) ...

  7. POJ-1661-Help Jimmy(DP, 递推)

    链接: https://vjudge.net/problem/POJ-1661 题意: "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同 ...

  8. 03_已解决 [salt.master :2195][ERROR ][6219] Failed to allocate a jid. The requested returner 'mysql' could not be loaded.

    总结: 对于python2.7环境下的salt来说,要安装pip install mysql-python 对于python3环境下的salt来说,pip install mysqlclient的时候 ...

  9. 019-020_STM32程序移植之_W5500连接noenet

    (一)本次实验是将数据通过W5500模块传输到onenet平台上面去 (二)显示内容,onenet平台数据变化曲线 (三)相关网站: 1.onenet网站:https://open.iot.10086 ...

  10. MySQL percona-toolkit工具详解

    一.检查和安装与Perl相关的模块 PT工具是使用Perl语言编写和执行的,所以需要系统中有Perl环境. 依赖包检查命令为: rpm -qa perl-DBI perl-DBD-MySQL perl ...