技术开发 频道

.NET中锁6大处理方法 悲观乐观自己掌握

  解决方案4:使用“读已提交的”解决“脏读取”问题

  关于“读已提交的”的一些关键点:

   • 它是SQL Server默认的事务隔离级别。

   • 它只读取已提交的数据,换句话说就是,任何未提交的数据它都会置之不理,直到数据提交为止,下图对其进行了详细解释,你也可以看到更新。

1

  图 11 读已提交模式解析

  如果你想看到上图所述的情况,只需要按照下面的步骤做就可以了:

   • 打开两个查询窗口,执行一个更新事务,但不提交;

   • 在第二个窗口中执行查询时,会显示如下图所示的查询被阻止的提示。

1

  图 12 查询被阻止,直到更新事务提交后才能执行

  “读已提交的”对立面是“读未提交的”吗?

  是的,读未提交的是读已提交的对立面,当你设置读未提交的事务隔离级别时,未提交的数据也被读取了。

  关于“读已提交的”关键点:

   • 未提交的是可见的,因此脏读取是可能的;

   • 没有锁被抓住;

   •  当锁不重要时很有用,更重要的是并发性和吞吐量。

  如果你也想测试一下,试试下面的SQL语句,它执行一个更新然,在等待20秒后回滚,在此期间如果你执行查询,返回的是未提交的数据,但20秒后,你再查询,返回的将会以前的旧数据,因为提交的数据已回滚。

set transaction isolation level read uncommitted
Begin Tran

Update customer
set CustomerName='Changed' where CustomerCode='1001'
WAITFOR DELAY '000:00:20'
rollback tran

set transaction isolation level read uncommitted
select * from Customer where CustomerCode='1001'

 

  解决方案5:使用重复读解决丢失更新和非重复读

  给重复读设置隔离级别后,其他人就不能读取和更新数据,关于重复读隔离级别的关键点包含:

    • 当为查询设置重复事务隔离级别时,只读取已提交的数据。

    • 当你使用重复读选择一条记录时,其它事务将不能更新该条记录,但查询是可以的。

   • 如果在更新查询中设置了可重复事务,必须要等到事务完成才能读和更新相同的记录。

   •  当选择和更新查询被设置为可重复读,其它事务可以插入新记录,换句话说就是虚幻行是可能的。

  如果你想测试这个隔离级别,执行下面的语句,然后尝试查询和更新查询,它们都将被阻止,50秒后你才能看到数据。

set transaction isolation level repeatable read
Begin Tran
Update customer
set CustomerName='Changed' where CustomerCode='1001'
WAITFOR DELAY '000:00:50'
rollback tran

 

  如果在重复读模式下执行下面的查询语句,在50秒内你啥也干不了,直到事务完成后你才能得到查询结果。

set transaction isolation level repeatable read
begin tran
select * from Customer where CustomerCode='1001'
WAITFOR DELAY '000:00:50'
commit tran

 

  注意,在此期间你可以添加CustomerCode=’1001’的新记录,换句话说就是虚幻行是可能的。

  解决方案6:使用序列化隔离级别解决虚幻行问题

  这是较高级的隔离级别,在此期间,其它事务是不能更新,查询和插入记录的,关于序列化事务的一些关键点包含:

   • 当隔离级别是序列化时,没有其它事务可以插入,更新,删除或查询。

   • 会出现许多阻塞,但所有并发性问题都能得到解决。

0
相关文章