SQLSERVER Update 行锁(rowlock)

 

在高并发的状况下,关系型数据库死锁是很难避免的问题,研发能作的是,尽可能减小死锁的可能性,那么就要求研发对数据库锁的机制有至关的了解,从而针对问题,尽量的避免死锁的发生。今天抽空,谈一谈关于update语句条件对锁的影响。我看了网络上的一篇文章,大体意思是sql

在进行update操做时,where条件是否使用主键或索引,对锁的级别将会有影响,具体内容以下:数据库

下面摘自网络的一段问内容:服务器

ROWLOCK告诉 SQL  Server只使用行级锁。ROWLOCK语法能够使用在SELECT, UPDATE和DELETE语句中,不过 我习惯仅仅在UPDATE和DELETE语句中使用。若是在UPDATE语句中有指定的主键,那么就老是会引起行级锁的。可是当SQL  Server对几个这种UPDATE进行批处理时,某些数据正好在同一个页面(page),这种状况在当前状况下  是颇有可能发生的,这就象在一个folder中,建立一个新文件须要较长的时间,而同时你又要去更新该folder中的某些文件。当页面锁引起后,事情就开始变得糟糕了。而若是在UPDATE或者DELETE 时,没有指定主键,数据库固然认为不少数据会收到影响,那样 就会直接引起页面锁,事情一样变得糟糕。
经过指定使用行级锁,这种状况能够获得避免。可是须要当心的是,若是你错误地使用在过多行上,数据库并不会聪明到自动将行级锁升级到页面锁,服务器也会由于行级锁的开销而消耗大量的内存和CPU,直至没法响应。尤为主要留意的是 企业管理器中"管理/当前活动"(Management /Current  Activity)这一项。该项会花较长的时间来载入锁的信息。这些信息是十分有用的,当你使用行级锁后,你若是在"锁/处理" (Locks/Processes)下看到几百个锁,一点都不奇怪,而偏偏应该庆幸锁超时和死锁的问题减小了。   网络

 

验证并发

为此,我建了一张表,进行update操做。高并发

首先,根据非主键字段MessageId,进行更新,打开一个事务,咱们称为sql1吧。code

begin tran 
  update [Messages] set RecordDate=GETDATE() where MessageId='7dd2de03-7693-4dd2-adbf-093e00b3cf7d';
  waitfor delay '00:00:05' 
  commit tran

然再打开一个会话,编写一个根据主键更新的sql,咱们称为sql2吧blog

update [Messages] set RecordDate=GETDATE() where Id='1326';

这种状况下,按照文中所说,在执行第一个sql后,再执行第二段sql,因为事务中的update语句条件根据非主键更新的,全部致使pagelock,因而,咱们在事务提交前,执行第二段SQL,就会处于等待状态。索引

而后咱们在作第二个验证,把事务中的update where条件改为主键,咱们称为sql3吧。事务

begin tran
  update [Messages] set RecordDate=GETDATE() where Id='1327'  
  waitfor delay '00:00:05' 
  commit tran

一样等待5秒。

而后先执行sql3,启动sql3后,立马执行sql2,看看效果,

直接是一行受影响,这也就验证了咱们这篇文章中的观点:"若是在UPDATE语句中有指定的主键,那么就老是会引起行级锁的"。

相关文章
相关标签/搜索