数据库事务隔离级别、脏读 重复读 不可重复读 幻读

数据库事务四种隔离级别

1、Read Uncommitted(读未提交) :事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”、“幻读”和“不可重复读取”。

2、READ COMMITTED (读提交):大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,但不能避免“幻读”和“不可重复读取”。该级别适用于大多数系统。

3、REPEATABLE READ(可重复读) :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但不能避免“幻读”,但是带来了更多的性能损失。

4、Serializable (串行化):最严格的级别,事务串行执行,资源消耗最大;

脏读、不可重复读、可重复读、幻读

脏读(能读取修改未提交的数据):所谓脏读,其实就是读到了别的事务回滚前的脏数据,也就是说,当前事务读到的数据是别的事务想要修改成为的但是没有修改成功的数据。

a,b两个事务同时存活的情况下:
a  事务把一条数据修改了,但是没有提交。 
b  事务是可以查询的时候,是可以读到a事务修改并没有提交的数据

不可重复读(能读取到修改且提交的数据):也就是说,当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配,也就照应了不可重复读的语义。

a,b两个事务同时存活的情况下:
a 事务把一条数据修改了,并且提交了。age=18 --->age=19
b 事务在事务内能读取到a事务修改后并提交的数据。age=19
不可重复读:是原来的没有被a事务修改的原数据,不能重读的去读取了,只能读到提交后的数据。

可重复读(就算别人修改数据,我还是能读取到之前的没有被修改的数据):

a,b两个事务同时存活的情况下:
a 事务把一条数据修改了,并且提交了。age=18 --->age = 19
b 事务在事务内是读取不到a事务修改后并提交的结果。读取的时候,age= 18
可重复读:是原来的数据,就算被其他事务修改了,还是能读取到原理没有被修改前的数据。

幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。也就是说,当前事务读第一次取到的数据比后来读取到数据条目少。

不可重复读和幻读比较:
两者有些相似,但是前者针对的是update或delete,后者针对的insert。

mysql使用悲观锁

原生的sql语句:
1 开启事务
2 查询的时候加锁---》select * from user where id =1 for update
3 当结束事务锁就被释放
django中的:
1 开始事务
2 在查询的时候 ----》 User.objects.select_for_update().filter(id =1 ).first()
3 可以对数据进行修改,数据永远不会被比如人修改,只有你自己能动
4 当结束事务锁就被释放

mysql使用乐观锁

如果使用乐观锁,mysql隔离级别要变成read committed,在django2.0以后,用乐观锁不需要修改隔离级别

乐观本质不是锁,是通过代码级别实现数据安全
1 开始事务
2 查询的时候不要做任何操作data= User.objects.filter(id =1 ).first()将这个条数据中的age在原来的基础上加1
3 在修改数据的时候。User.objects.filter(id = 1 ,age = data.age).update(age = data.age+1)从而保证在我查询到我修改的这段时候,没有人动过我的数据。
4 如果3中的更新的影响行数为1,说明数据没有被别人改动,只我动,如果3中的影响行数为0,说明该数据已经被别人修改。这时我们想要改数据,就必须重复执行2-3两不,直到3有影响行数。

 

posted @ 2020-03-18 09:02  Hank·Paul  阅读(441)  评论(0编辑  收藏  举报