事务隔离级别&悲观乐观锁

本文是对https://github.com/ScrappyZhang/python_web_Crawler_DA_ML_DL/blob/master/web%E5%85%A8%E6%A0%88%E5%BC%80%E5%8F%91/Django%E7%94%B5%E5%95%86%E7%BD%91%E7%AB%99%E5%BC%80%E5%8F%91%E5%AE%9E%E4%BE%8B/19_%E7%94%A8%E6%88%B7%E5%B9%B6%E5%8F%91%E4%B8%8B%E5%8D%95%E9%97%AE%E9%A2%98.md文章的理解,做笔记留存

数据库事务隔离级别

1.事务的并发问题

  • 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  • 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
  • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

2.事务隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

默认的事务隔离级别是 repeatable-read

  • read-uncommitted (读-未提交)

(1)事务A , 事务B 同时读取一行数据 100.

(2)A 修改为50 但还没提交,B 查看该行数据是50;

(3)A 没提交,回滚了操作,B查看数据是100; ## 那个50就是脏数据, 这个即是脏读问题

  • read-committed(读-提交) ## 写时锁行

(1)事务A , 事务B 同时读取一行数据100.

(2)A 修改为50, 但没提交 , B查看还是100; ##解决了脏读问题

(3)A 提交后,B查看是50; ## 出现新问题 就是重复读时, 两次数据不一致 这个即是不可重复读问题

  • repeatable-read(重复-读) ##写时锁表

(1)事务A , 事务B 同时读取一行数据100.

(2)A 修改为50,没提交,B查看还是100;

(3)A提交后,B查看还是100; ##解决了不可重复读问题

(4)B提交事务后,再次查看数据是50 ##出现新问题, B提交后,再次查询数据不一致,这个即是幻读问题

  • serializable (串行) ## 读写时锁表

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

3.总结

  • mysql中默认事务隔离级别是可重复读时并不会锁住读取到的行
  • 事务隔离级别为读提交时,写数据只会锁住相应的行
  • 事务隔离级别为可重复读时,写数据会锁住整张表
  • 事务隔离级别为串行化时,读写数据都会锁住整张表
  • 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,鱼和熊掌不可兼得。

乐观锁和悲观锁

悲观锁

概念: 在整个数据处理过程中,将数据处于锁定状态

  • sql中的使用方法

首先,将事务隔离级别设置为READ-COMMITTED ,采用数据库本身的悲观锁命令 for update

select number from money where id=1 for update;

只有commit后才能操作这行数据

  • Django中的模型管理器悲观锁方法
select_for_update(nowait=False, skip_locked=False, of=())
等价于: SELECT ... FOR UPDATE 

例如:entries = Entry.objects.select_for_update().filter(author=request.user)

乐观锁

概念:乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回用户错误的信息,让用户决定如何去做。

实现方式 :

使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。

何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。

当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。
示意图如下:

事务隔离级别&悲观乐观锁_第1张图片
Snipaste_2018-07-26_23-17-28.png

如果是商城中的订单使用乐观锁解决超卖问题,可以将库存当做版本字段.

你可能感兴趣的:(事务隔离级别&悲观乐观锁)