继续上篇博客 事务特性及隔离问题。
我们来做一个关于隔离级别的实验,将演示各个级别导致的隔离问题。
我们先打开两个MySQL窗口,来模拟并发操作。
set transaction isolation level Read uncommitted;set session transaction isolation level read committed;修改隔离级别后,该窗口就被允许发生脏读。现在给这两个窗口命名一下,方便后续讲解,我们就令设置了事务隔离级别的窗口为B,另一个窗口为A。start transaction;现在同时查看两个用户的表数据
update account set money = money - 200 where name = 'aaa';
update account set money = money + 200 where name = 'bbb';
然后查询表数据

转账操作成功执行。
此时在B窗口进行查询
左边是A窗口,右边是B窗口
会发现,B窗口读取到了A窗口未提交的数据,此时在A窗口进行回滚操作,再次查询表数据

两个用户的表数据都回到了原来的状态,但是B窗口在之前查询数据的时候,是确认了aaa账户转账了200元给bbb账户的,而此时转账操作却被回滚了,钱又相当于转回给了aaa账户,此时就造成了bbb账户的经济损失,这就是脏读现象。
set transaction isolation level Read committed;

set transaction isolation level Repeatable read; update account set money = money-500 where name = 'bbb';
update account set money = money+500 where name = 'ccc';
然后提交A窗口的操作,查询两边的表数据

发现即使A窗口提交了操作,B窗口的表数据仍然不会被改变,证实了刚才的结论,但是该隔离级别会导致虚读的产生。很遗憾的是,虚读无法为大家举例了,因为虚读发生的概率是非常低的,但是方法还是给大家介绍一下。
在A窗口插入一条数据,输入insert into account values (4,‘ddd‘,1000);,然后在B窗口进行表数据查询,如果查询到了A窗口插入的数据,说明发生了虚读,但很显然,这个现象并没有发生,所以图我就不贴了。
insert into account values(5,‘eee‘,1000);当你按回车键执行语句时,你会发现,A窗口并没有马上执行sql语句,而是阻塞了。那这是为什么呢?因为该级别是最高隔离级别,采取串行处理方法,在一个用户操作该数据库时,不允许别的用户操作。那么接下来请注意了,在JDBC程序中如何控制数据库的隔离级别呢?
在Connection接口中定义了五个字段,它们就是用来控制对应的隔离级别的,只需要调用setTransactionIsolation(int level)方法并将对应的字段传入,即可达到控制隔离级别的效果。如果不设置隔离级别,将采用数据库默认级别,Oracle和MySQL数据库的默认级别是什么还记得吗?不记得的话就再次阅读一下我的上一篇博客。
还有一个需要注意的地方,在MySQL5.5的64位版本中,输入set transaction isolation level代码并不能成功修改事务隔离级别,这又是为什么呢?因为在MySQL5.0的规范中就规定,该条语句必须加上一个关键字session,也就是说,想要成功修改,你得输入set session transaction isolation level才能成功修改。
原文:https://www.cnblogs.com/blizzawang/p/11411329.html