Title

数据库的隔离级别和乐观锁悲观锁

事务是有隔离级别

read uncommited (读未提交):不做任何隔离,具有脏读,不可重读,幻读的问题

read committed (读提交):可以防止脏读,不能防止不可重复读和幻读的问题

repeatable read(可重复读):可以防止脏读,不可重复读,不能防止幻读(mysql的默认隔离级别)

serializable(串行化):数据库运行为串行,以上问题都可以防止,但是性能低,相当于将整个库都加锁了

下面的解释都用这个user表

nameage
jason 38
   
   

 

脏读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的)

1 a  开启事务  将jason的年龄改成 18岁,但是没有提交事务
2 b 开始事务 读取jason的年龄,发现是18岁。

上述的问题,
假设a事务回滚,b事务使用的数据就是错误的,就导致程序数据不正确。

不可重复度(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的)

1 a  开始事务  将jason的年龄改成18岁,但是提交了
2 b 开启事务 读取jason的年龄就能读取a事务修改后的jason年龄18岁。

可重读读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的)

1 a  开始事务  将jason的年龄改成18岁,但是提交了
2 b 开启事务 读取jason的年龄不能读取a事务修改后的jason年龄18岁。而是读取的是38岁

幻读(a,b同时开始事务,a,b再事务,没有哪一个结束,只有两个都进入事务后,才能结束期中一个事务,两个事务都是存活的)

#概念和不可重读有点像,不可重复度是站在修改的基础上,而幻读是站在新增的基础上
1 a 开始事务 将所有的的年龄改成18岁
2 b 开始事务 新增一条数据数据name=tank,age=19,而且提交了。
3 a 重新查, 发现有一条数据 的age=19,这就是所谓的幻读。

如何看msql的隔离级别

select @@global.tx_isolation;

如何修改事务的隔离级别

#修改配置文件
transaction-isolation=Read-Committed
#修改后一定要重启数据库

为什么会出现“脏读”?因为没有“select”操作没有规矩。

为什么会出现“不可重复读”?因为“update”操作没有规矩。

为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。

“读未提(Read Uncommitted)”能预防啥?啥都预防不了。

“读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。

“可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。

“串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。

https://baijiahao.baidu.com/s?id=1611918898724887602&wfr=spider&for=pc

数据库的乐观锁与悲观锁(是建立再事务的基础上)

悲观锁

悲观锁的概念,他觉有人会修改我读的数据。那我就再查的时候,对数据进行锁定。

select age from user where id=1 for update;
比如 上面的查出来的 age =18
update age改成age = age+ 1
如果别人开启了悲观锁这条数据就会被锁定卡住,只能等别人的事物结束才能操作,所以少用慎用
如果该次查询走了索引,那就是行锁,如果没有走索引就是表锁。

如何释放锁呢?结束事务就释 放了锁。
django中的orm是如果用悲观锁?
user.objects.select_for_update().filter(id=1).first()

乐观锁

乐观锁的本质不是锁。他是通过代码来实现锁的。他觉的别人不会修改的他的数据。他就读数据不会被别人修改。最后再修改该条数据,再where条件中添加,之前查出来的数据。以保证数据的安全性
select age from user where id=1 ;
比如 上面的查出来的 age =18  
20
update age改成age = age+ 1 ====》19

乐观锁:
update age改成age = age+ 1 where age =18 and id =1 ====》19
如果我发现不是18,上面的影响行数是0,这样说明数据是不安全的,重新for循环或者其他方式获取数据重新执行
#如果是可重复读,上面的乐观锁无效,必须改成read committed,因为可重复读会读取到之前的数据,所以乐观锁的条件就会成立
a update age改成age = age+ 1 ====》19 提交


b select age from user where id=1; --->18

update age改成age = age+ 1 where age =18 and id =1 ====》19 ---->数据已经被改

 

posted @ 2020-05-25 15:48  Mr江  阅读(355)  评论(0编辑  收藏  举报