下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

数据库弱一致性隔离级别有多少个?

作者:课课家教育     来源: http://www.kokojia.com点击数:674发布时间: 2017-08-27 10:00:41

标签: 数据库数据库基础数据库事务

  在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。

  数据库事务的隔离级别有4个,由低到高依次为Readuncommitted(未授权读取、读未提交)、Readcommitted(授权读取、读提交)、Repeatableread(可重复读取)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

      小编大家就跟着小编来看一看它们的详细内容吧~

  READUNCOMMITTED

  READUNCOMMITTED是限制性最弱的隔离级别,因为该级别忽略其他事务放置的锁。使用READUNCOMMITTED级别执行的事务,可以读取尚未由其他事务提交的修改后的数据值;这些行为称为“脏”读。。这是因为在Read Uncommitted级别下,读取数据不需要加S锁,这样就不会跟被修改的数据上的X锁冲突。比如,事务1修改一行,事务2在事务1提交之前读取了这一行。如果事务1回滚,事务2就读取了一行没有提交的数据,这样的数据我们认为是不存在的。

  READCOMMITTED

  READCOMMITTED(Nonrepeatablereads)是SQLServer默认的隔离级别。该级别通过指定语句不能读取其他事务已修改但是尚未提交的数据值,禁止执行脏读。在当前事务中的各个语句执行之间,其他事务仍可以修改、插入或删除数据,从而产生无法重复的读操作,或“影子”数据。比如,事务1读取了一行,事务2修改或者删除这一行并且提交。如果事务1想再一次读取这一行,它将获得修改后的数据或者发现这一样已经被删除,因此事务的第二次读取结果与第一次读取结果不同,因此也叫不可重复读。

  实验1

  query1:事务1

数据库弱一致性隔离级别有多少个?_数据库_数据库基础_数据库事务_课课家教育

  查看锁的情况如下图所示,我们发现在只有在数据库级别的S锁,而没有在表级别或者更低级别的锁,这是因为在ReadCommitted级别下,S锁在语句执行完以后就被释放。

查看锁的情况如下图所示,我们发现在只有在数据库级别的S锁,而没有在表级别或者更低级别的锁,这是因为在ReadCommitted级别下,S锁在语句执行完以后就被释放。

  query2:事务2

query2:事务2

  在开启另外一个update事务以后,我们再去查看当前的锁状况,如下图所示,我们发现在表(Object)级别上加了IX锁,在这张表所在的Page上也加了IX锁,因为表加了聚集索引,所以在叶子结点上加了X锁,这个锁的类型是KEY。

在开启另外一个update事务以后,我们再去查看当前的锁状况,如下图所示,我们发现在表(Object)级别上加了IX锁,在这张表所在的Page上也加了IX锁,因为表加了聚集索引,所以在叶子结点上加了X锁,这个锁的类型是KEY。

  然后我们回到事务1当中再次执行查询语句,我们会发现查询被阻塞,我们新建一个查询query3来查看这个时候的锁状况,其查询结果如下,我们可以发现查询操作需要在KEY级别上申请S锁,在Page和表(Object)上面申请IS锁,但是因为Key上面原先有了X锁,与当前读操作申请的S锁冲突,所以这一步处于WAIT状态。

然后我们回到事务1当中再次执行查询语句,我们会发现查询被阻塞,我们新建一个查询query3来查看这个时候的锁状况,其查询结果如下,我们可以发现查询操作需要在KEY级别上申请S锁,在Page和表(Object)上面申请IS锁,但是因为Key上面原先有了X锁,与当前读操作申请的S锁冲突,所以这一步处于WAIT状态。

  如果此时提交事务2的update操作,那么事务1的select操作不再被阻塞,得到查询结果,但是我们发现此时得到的查询结果与第一次得到的查询结果不同,这也是为什么将readcommitted称为不可重复读,因为同一个事物内的两次相同的查询操作的结果可能不同。

  REPEATABLEREAD

  REPEATABLEREAD是比READCOMMITTED限制性更强的隔离级别。该级别包括READCOMMITTED,并且另外指定了在当前事务提交之前,其他任何事务均不可以修改或删除当前事务已读取的数据。并发性低于READCOMMITTED,因为已读数据的共享锁在整个事务期间持有,而不是在每个语句结束时释放。比如,事务1读取了一行,事务2想修改或者删除这一行并且提交,但是因为事务1尚未提交,数据行中有事务1的锁,事务2无法进行更新操作,因此事务2阻塞并且回滚。如果这时候事务1想再一次读取这一行,它读取结果与第一次读取结果相同,因此叫可重复读。

  实验2

  query1:事务1

REPEATABLEREAD    REPEATABLEREAD是比READCOMMITTED限制性更强的隔离级别。该级别包括READCOMMITTED,并且另外指定了在当前事务提交之前,其他任何事务均不可以修改或删除当前事务已读取的数据。并发性低于READCOMMITTED,因为已读数据的共享锁在整个事务期间持有,而不是在每个语句结束时释放。比如,事务1读取了一行,事务2想修改或者删除这一行并且提交,但是因为事务1尚未提交,数据行中有事务1的锁,事务2无法进行更新操作,因此事务2阻塞并且回滚。如果这时候事务1想再一次读取这一行,它读取结果与第一次读取结果相同,因此叫可重复读。    实验2    query1:事务1

  查询锁状态的结果如下图所示,我们发现在KEY上面加了S锁,在Page和Object上面加了IS锁,这是因为在RepeatableRead级别下S锁要在事务执行完以后才会被释放。

查询锁状态的结果如下图所示,我们发现在KEY上面加了S锁,在Page和Object上面加了IS锁,这是因为在RepeatableRead级别下S锁要在事务执行完以后才会被释放。

  query2:事务2

query2:事务2

  执行上述update操作的时候发现该操作被阻塞,这是因为update操作要加排它锁X,而因为原先的查询操作的S锁没有释放,所以两者冲突。我们新建一个查询3执行查询锁状态操作,发现结果如下图所示,我们可以发现是WAIT发生在对KEY加X锁的操作上面。

执行上述update操作的时候发现该操作被阻塞,这是因为update操作要加排它锁X,而因为原先的查询操作的S锁没有释放,所以两者冲突。我们新建一个查询3执行查询锁状态操作,发现结果如下图所示,我们可以发现是WAIT发生在对KEY加X锁的操作上面。

  此时再次执行查询1中的select操作,我们发现查询结果跟第一次相同,所以这个叫做可重复读操作。但是可重复读操作并不是特定指两次读取的数据一模一样,RepeatableRead存在的一个问题是幻读,就是第二次读取的数据返回的条目数比第一次返回的条目数更多。

  比如在RepeatableRead隔离级别下,事务1第一次执行查询selectidfromuserswhereid>1andid<10,返回的结果是2,4,6,8。这个时候事务1没有提交,那么对2,4,6,8上面依然保持有S锁。此时事务2执行一次插入操作insertintouser(id)valuse(3),插入成功。此时再次执行事务1中的查询,那么返回结果就是2,3,4,6,8。这里的3就是因为幻读而出现的。因此可以得出结论:REPEATABLEREAD隔离级别保证了在相同的查询条件下,同一个事务中的两个查询,第二次读取的内容肯定包换第一次读到的内容。

  SERIALIZABLE

  SERIALIZABLE是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。该级别包括REPEATABLEREAD,并增加了在事务完成之前,其他事务不能向事务已读取的范围插入新行的限制。比如,事务1读取了一系列满足搜索条件的行。事务2在执行SQLstatement产生一行或者多行满足事务1搜索条件的行时会冲突,则事务2回滚。这时事务1再次读取了一系列满足相同搜索条件的行,第二次读取的结果和第一次读取的结果相同。

  重复读与幻读

  重复读是为了保证在一个事务中,相同查询条件下读取的数据值不发生改变,但是不能保证下次同样条件查询,结果记录数不会增加。

  幻读就是为了解决这个问题而存在的,他将这个查询范围都加锁了,所以就不能再往这个范围内插入数据,这就是SERIALIZABLE隔离级别做的事情。

  隔离级别与锁的关系

  1.在ReadUncommitted级别下,读操作不加S锁;

  2.在ReadCommitted级别下,读操作需要加S锁,但是在语句执行完以后释放S锁;

  3.在RepeatableRead级别下,读操作需要加S锁,但是在事务提交之前并不释放S锁,也就是必须等待事务执行完毕以后才释放S锁。

  4.在Serialize级别下,会在RepeatableRead级别的基础上,添加一个范围锁。保证一个事务内的两次查询结果完全一样,而不会出现第一次查询结果是第二次查询结果的子集。

  小编结语:

  更多内容尽在课课家教育!

赞(11)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程