【lesson29】MySQL事务不同隔离级别之间的区别演示

文章目录

  • 读未提交
  • 读提交
  • 可重复读
  • 串行化
  • 总结

读未提交

【lesson29】MySQL事务不同隔离级别之间的区别演示_第1张图片
我们看到这时的隔离级别是读提交,那么我们就要把隔离级别改为,读未提交。
在这里插入图片描述
【lesson29】MySQL事务不同隔离级别之间的区别演示_第2张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第3张图片
我们可以看到两个终端的mysql隔离级别已经都被改成了读未提交。

开始演示读未提交:
开启2个事务【lesson29】MySQL事务不同隔离级别之间的区别演示_第4张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第5张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第6张图片
事务2读取到了事务1还未提交的数据,这就是读未提交。
【lesson29】MySQL事务不同隔离级别之间的区别演示_第7张图片

一个事务能读到另一个事务还未提交的数据这叫脏读。

读提交

【lesson29】MySQL事务不同隔离级别之间的区别演示_第8张图片
我们现在的隔离级别是读未提交,那么我们把它更改为读提交
【lesson29】MySQL事务不同隔离级别之间的区别演示_第9张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第10张图片
重启mysql客户端后我们就会看到,隔离级别修改成功。

开始演示读提交:
开启2个事务
【lesson29】MySQL事务不同隔离级别之间的区别演示_第11张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第12张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第13张图片

【lesson29】MySQL事务不同隔离级别之间的区别演示_第14张图片
1个事务结束提交了,另一个事务就能看到该已经结束事务修改的数据,如果该事务未结束就看不到叫做读提交。

所以在事务1提交之前,事务2的数据不是最新的。

在多个事务并发运行时,任何一个有读取条件的事务,它极有可能在其它事务未提交修改数据时看不到修改的数据,提交了自己未结束就可以看到修改的数据,就会导致同一个事务内部两次select可能看到的结果不一样。这种现象叫不可重复读。

那么不可重复读是问题吗?
举例子:
今年到年底了,老板准备给不同工资的员工发送不同的礼品。
老板把这个任务交代给了总经理。
于是总经理就计划出了下列的方案。
[1000,2000) 送水杯
[2000,3000) 送键盘
[3000,4000) 送微波炉
[4000,5000) 送电视
[5000,10000) 送手机
然后总经理让程序员小张,根据方案找出各个工资对应的人员。

于是小张就启动了一个事务
beigin;
select name from emp where
sal >=1000 and sal < 2000;
2000 3000
3000 4000
4000 5000
5000 10000
commit;

但是在小张运行事务的同时。
Tom觉得自己工资很低就3000块,但是自己对公司的贡献很大,于是Tom找到老板让老板给自己涨工资,老板一看确实Tom贡献很大,于是就让小王把Tom的工资涨到4500

于是小张就启动了一个事务。
begin;
update emp set sal = 4500 where name = ‘Tom’;
commit;

但是这时候可能就遇到一个情况:小张,小王的事务同时在运行。
小王还没改完,小张在3000-4000工资处查到了Tom。
小王改完了,小张刚好又在4000-5000工资处查到了Tom。
所以这里就出现了问题,小张可能会疑惑,Tom的工资怎么既在3000-4000,又在4000-5000呢?

所以不可重复读是问题。

可重复读

【lesson29】MySQL事务不同隔离级别之间的区别演示_第15张图片
我们初始的隔离级别是读提交,那么接下来我们要把它改成可重复读。
在这里插入图片描述
重启mysql客户端
【lesson29】MySQL事务不同隔离级别之间的区别演示_第16张图片
我们看到修改成功了。

开始演示可重复读:
开启2个事务
在这里插入图片描述
【lesson29】MySQL事务不同隔离级别之间的区别演示_第17张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第18张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第19张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第20张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第21张图片
重启一个事务
【lesson29】MySQL事务不同隔离级别之间的区别演示_第22张图片
我们发现,确实在事务重启后就能看见修改的数据内容。

再次演示可重复读:
开启事务

事务2原始数据:
【lesson29】MySQL事务不同隔离级别之间的区别演示_第23张图片
事务1修改数据:
【lesson29】MySQL事务不同隔离级别之间的区别演示_第24张图片
事务2查看数据:
【lesson29】MySQL事务不同隔离级别之间的区别演示_第25张图片
结束事务2
重启一个事务
【lesson29】MySQL事务不同隔离级别之间的区别演示_第26张图片

多次查看,发现终端A在对应事务中insert的数据,在终端B的事务周期中,也没有什么影响,也符合可重复的特点。但是,一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读(phantom read)。很明显,MySQL在RR级别的时候,是解决了幻读问题的(解决的方式是用Next-Key锁(GAP+行锁)解决的。这块比较难,有兴趣同学了解一下)

串行化

【lesson29】MySQL事务不同隔离级别之间的区别演示_第27张图片
我们看到初始隔离级别是可重复读,那么把它改成串行化
【lesson29】MySQL事务不同隔离级别之间的区别演示_第28张图片
【lesson29】MySQL事务不同隔离级别之间的区别演示_第29张图片
修改成功!

演示串行化:
开启2个事务
【lesson29】MySQL事务不同隔离级别之间的区别演示_第30张图片

事务1和事务2查看数据
【lesson29】MySQL事务不同隔离级别之间的区别演示_第31张图片
事务1:删除数据
【lesson29】MySQL事务不同隔离级别之间的区别演示_第32张图片
我们发现卡在这里
【lesson29】MySQL事务不同隔离级别之间的区别演示_第33张图片
但是事务2还可以查数据。

【lesson29】MySQL事务不同隔离级别之间的区别演示_第34张图片
最后我们发现事务1删数据超时了。
【lesson29】MySQL事务不同隔离级别之间的区别演示_第35张图片

这时我们把事务2结束掉;
【lesson29】MySQL事务不同隔离级别之间的区别演示_第36张图片
然后事务1再删除数据
【lesson29】MySQL事务不同隔离级别之间的区别演示_第37张图片
我们这时就会发现,当只有事务1在运行的时候,对数据修改才会成功。

对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用

总结

  • 其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平衡点。
  • 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了 。幻读的重点在于新增:同样的条件,第1次和第2次读出来的记录数不一样
  • 说明: mysql 默认的隔离级别是可重复读,一般情况下不要修改
  • 上面的例子可以看出,事务也有长短事务这样的概念。事务间互相影响,指的是事务在并行执行的时候,即都没有commit的时候,影响会比较大。
    【lesson29】MySQL事务不同隔离级别之间的区别演示_第38张图片

你可能感兴趣的:(MySQL,mysql,数据库,服务器)