论坛首页 Java企业应用论坛

MySQL的隔离级别

浏览 4418 次
精华帖 (1) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-04-16  

一、读未提交(READ-UNCOMMITTED

 

当事务隔离级别设置为READ-UNCOMMITTED(读未提交)时,在这种状态下,一个会话更新的数据会被其他的会话马上看到,即使该更新的数据尚未被事务所提交(commit)。

 

打开两个会话,分别设置它们的隔离级别。

 

会话一:



 

由图可见,会话一的session隔离级别被设置为READ-UNCOMMITTED(读未提交)。

 

会话二:



 

由图可见,会话二的session隔离级别被设置为REPEATABLE-READ(可重复读)。

 

我们将在表classes(存储引擎为InnoDB)下做测试,首先先来看下classes都已有哪些数据:



 

由图可见classes里面现在有3条数据。

 

在会话一中新增一条新数据但不提交:



 

 

如图所示,在会话一中新增数据“Middle four”,虽未提交,但在会话一中马上就能查看到。

 

那在会话二中是否能看到?



 

由图可见,会话二无法看到在会话一中未提交的数据。为什么会出现这种情况?因为会话二中的session隔离级别为REPEATABLE-READ,无法脏读,即无法查看到未提交数据。那是否更改为READ-UNCOMMITTED就可以查看得到呢?



 

如图所示,当session隔离级别更改为READ-UNCOMMITTED时,会话二中即马上能看到会话一中未提交的数据。

 

如果此时会话一中执行回滚(rollback),那么会话一和会话二都会马上看到class_num=’10004’的数据已不存在。

 

会话一:



 

会话二:



 

结论:当一个会话的(session)事务隔离级别被设置为READ-UNCOMMITTED时,那么它将可以马上看到其他会话更新的未提交数据,也既会出现脏读。

 

 

二、读已提交(READ-COMMITTED

 

当事务隔离级别设置为READ-COMMITTED(读已提交)时,在这种状态下,一个会话更新的数据不会被其他的会话马上看到,除非该更新的数据已被事务所提交(commit)。

 

将会话一和会话二的session隔离级别都设置为READ-COMMITTED

 

会话一:



 

会话二:



 

然后在会话一开启一个新事务,并插入一条新数据,但先不要提交,如图:



 

由图可知,此时会话一可以查到该未提交的数据,和前面session设置为READ-UNCOMMITTED一样,那是不是说明会话一出现了脏读?

 

看看会话二是否也可以查看得到:



 

由图可知,会话二无法读取到会话一中未提交的数据。那这就说明会话一中出现的情况(能读取自己未提交的数据)并不是脏读,因为会话二和会话一的隔离级别都是READ-COMMITTED,如果会话一出现了脏读,那么会话二也会出现。

 

那这是什么情况?本人认为这是因为它们是在同一个事务里,所以前面的操作对后面的操作是可见的,也即是后面的操作认为前面的操作已完成,所以它可以获取前面更新的数据。

 

此时会话一提交事务,会话二马上可以看到提交的事务:



 

总结:当一个会话的(session)事务隔离级别被设置为READ-COMMITTED时,那么它只可以看到其他会话已经提交的数据。

 

三、可重复读(REPEATABLE-READ

 

当事务隔离级别设置为REPEATABLE-READ(可重复读)时,在这种状态下,同一个事务中的多次查询结果都是一致的(既不会出现不可重复读的现象),即使在此期间其他会话更新了数据,这些数据对其也是不可见的。

 

将会话一和会话二的session隔离级别都设置为REPEATABLE-READ

 

会话一:



 

会话二:



 

此时在会话一中开启事务,并查看现有数据,先不做commit



 

现在一共有5条数据。此时,我们通过会话二插入一条新数据:



 

然后再回到会话一,重新查看数据:



 

由图可见,会话二更新的数据对其不可见。

 

会话一提交事务后再查看数据:



 

此时会话二添加的数据已可查看。

 

由此可见,当事务的隔离级别被设置为REPEATABLE-READ后,同一个事务中的select语句查出的结果都是一致的,其他事务在此期间提交的数据将对其不可见。

 

 

四、串行化(Serializable

 

当事务隔离级别设置为SERIALIZABLE(串行读)时,在这种状态下,一个会话事务中的select操作将会阻塞其他事务的写(addupdatedelete)操作,但不会阻塞读。

 

将会话一和会话二的(session)事务隔离级别都设置为SERIALIZABLE

 

会话一:



 

会话二:



 

在会话一开启新事务,然后select下数据,但先不做commit操作:



 

此时在会话二中插入一条新数据,发现无法插入,插入操作一直被阻塞:



 

select操作未被阻塞:



 

在会话一中执行commit操作,然后重新开启一个事务,并插入一条新数据,但先不提交:



 

此时在会话二中针对会话一新添的数据的任何写操作都会被阻塞:



 

但其他数据的读写操作不会被阻塞:



 

由此可以得出结论,当(session)事务的隔离级别被设置为SERIALIZABLE时,一个会话中的select操作会阻塞其他会话中的写操作,但不会阻塞select操作,而且一个会话中的写操作,会阻塞其他会话对同一条数据进行写操作。



 

  • 大小: 53.2 KB
  • 大小: 14.2 KB
  • 大小: 23.7 KB
  • 大小: 14.1 KB
  • 大小: 21.8 KB
  • 大小: 13.8 KB
  • 大小: 23.5 KB
  • 大小: 22.8 KB
  • 大小: 24.1 KB
  • 大小: 18.6 KB
  • 大小: 16.8 KB
  • 大小: 24.9 KB
  • 大小: 18.1 KB
  • 大小: 24.1 KB
  • 大小: 14.9 KB
  • 大小: 18.7 KB
  • 大小: 23.1 KB
  • 大小: 22.2 KB
  • 大小: 23.1 KB
  • 大小: 24.1 KB
  • 大小: 21.4 KB
  • 大小: 38.6 KB
  • 大小: 11 KB
  • 大小: 21.9 KB
  • 大小: 37.8 KB
  • 大小: 36.9 KB
  • 大小: 19.1 KB
   发表时间:2013-11-30  
这个写的很好。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics