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

  本文介绍了处理.NET中锁的6种方法,首先我们讨论一下并发性问题,然后讨论处理乐观锁的3种方法,乐观锁不能从根源上解决并发问题,因此后面我们介绍了悲观锁,最后介绍隔离级别如何帮助我们实现悲观锁,每个隔离级别都列举了示例进行说明,使得概念更加清晰。

  我们为什么需要锁?

  在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这就会产生冲突,这个就是著名的并发性问题。

我们为什么需要锁?

  图 1 并行性问题漫画

  如何解决并发性问题?

  借助正确的锁定策略可以解决并发性问题,资源被锁定后,其它进程想要访问它就会被阻止。

  并发会造成什么样的冲突?

  并发主要会导致四种常见的问题,详细情况请看下表。

问题简要描述解释
脏读取当一个事务读取其它完成一半事务的记录时,就会发生脏读取
  • 用户A和用户B看到的值都是5
  •  用户B将值修改为2
  •  用户A看到的值仍然是5,这时就发生了脏读取
不可重复读取在每次读数据时,如果你获得的值都不一样,那表明你遇到了不可重复读取问题
  • 用户A看到的值是5
  • 用户B将值改为2
  • 用户A刷新后看到的值仍然是5,这时就发生了不可重复读取
虚幻行如果update和delete SQL语句未对数据造成影响,很可能遇到了虚幻行问题
  • 用户A将所有值从5修改为2
  • 用户B使用值2插入一个新记录
  • 用户A查询所有值为2的记录,但却找不到,这时就发生了虚幻行
更新丢失一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失
  • 用户A将所有值从5更新为2
  • 用户B将所有值从2更新到5
  •  用户A丢失了他的更新

  如何解决上述冲突?

  答案是使用乐观锁或悲观锁,下面将进一步进行阐述。

我们为什么需要锁?

  图 2 乐观锁和悲观锁  

  什么是乐观锁?

  顾名思义,乐观锁假设多个事务相互不会影响对方,换句话说就是,在乐观锁模式下,没有锁操作会得到执行,事务只是验证是否有其它事务修改数据,如果有则进行事务回滚,否则就提交。

处理.<a href=/itjie/NETjishu/ target=_blank class=infotextkey>NET</a>中锁的6种方法

 图 3 乐观锁

  乐观锁是如何工作的?

  实现乐观锁的方法有多种,但基本原则都一样,总是少不了下面五个步骤:

  •记录当前的时间戳

  •开始修改值

  •在更新前,检查是否有其他人更新了值(通过检查新旧时间戳实现)

  • 如果不相等就回滚,否则就提交

处理.<a href=/itjie/NETjishu/ target=_blank class=infotextkey>NET</a>中锁的6种方法

  图 4 乐观锁的工作原理

  实现乐观锁的解决方案

  在.NET中,实现乐观锁的方法主要有三种:

  •数据集(Dataset):数据集是实现乐观锁的默认方法,在更新前它会检查新旧值。

  • 时间戳数据类型(timestamp):在你的表中创建一个timestamp数据类型,在更新时,检查旧时间戳是否等于新时间戳。

  •直接检查新旧值:在更新时检查旧值和新值是否相等,如果不相等就回滚,否则就提交。

  解决方案1:数据集

  正如前面所说的,数据集是处理乐观锁的默认方法,下面是一个简单的快照,在Adapter的update函数上有一个调试点,当我移除断点运行update函数时,它抛出如下图所示的并行异常错误。

处理.<a href=/itjie/NETjishu/ target=_blank class=infotextkey>NET</a>中锁的6种方法

  图 5 Update函数执行时抛出的异常错误

  如果你运行后端分析器,你将会看到更新语句检查当前值和旧值是否相等: 

exec sp_executesql N'UPDATE [tbl_items] SET [AuthorName] = @p1
 WHERE (([Id] = @p2) AND ((@p3 = 1 AND [ItemName] IS NULL)

OR ([ItemName] = @p4)) AND ((@p5 = 1 AND [Type] IS NULL)
OR ([Type]
= @p6)) AND ((@p7 = 1 AND [AuthorName] IS NULL)
OR ([AuthorName]
= @p8)) AND ((@p9 = 1 AND [Vendor] IS NULL)
OR ([Vendor]
= @p10)))',N'@p1 nvarchar(11),@p2 int,@p3
int,@p4 nvarchar(4),@p5 int,@p6 int,@p7
int
,@p8 nvarchar(18),@p9 int,@p10 nvarchar(2)',
@p1=N
'this is new',@p2=2,@p3=0,@p4=N'1001',@p5=0,@p6=3,@p7=0,
@p8=N
'This is Old
Author
',@p9=0,@p10=N'kk'

NET技术.NET中锁6大处理方法 悲观乐观自己掌握,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。