SQLServer中的锁(摘自网络)
使用 sys.dm_tran_locks 这个DMV (sp_lock) 查看锁信息
SELECT * FROM sys.dm_tran_locks
所包含的信息分为两类,以resource为开头的描述锁所在的资源的信息,另一类以request开头的信息描述
使用Profiler来捕捉锁信息
Locks
Lock:Acquired
Lock:Released
Lock:Timeout
扑捉时需要过滤掉SQL内部的锁,即SPID>=50即可
锁的粒度
锁是加在数据库对象上的。而数据库对象是有粒度的,比如同样是1这个单位,1行,1页,1个B树,1张表。因此,锁的粒度,是锁所在资源的粒度。
锁会给数据库带来阻塞,因此越大粒度的锁造成更多的阻塞,但由于大粒度的锁需要更少的锁,因此会提升性能。而小粒度的锁由于锁定更少资源,会减少阻塞,因此提高了并发,但同时大量的锁也会造成性能的下降。
RID用于锁定堆中的单个行的行标识符。
KEY索引中用于保护可序列化事务中的键范围的行锁。
PAGE数据库中的 8 KB 页,例如数据页或索引页。
EXTENT一组连续的八页,例如数据页或索引页。
HoBT堆或 B 树。 用于保护没有聚集索引的表中的 B 树(索引)或堆数据页的锁。
TABLE包括所有数据和索引的整个表。
FILE数据库文件。
APPLICATION应用程序专用的资源。
METADATA元数据锁。
ALLOCATION_UNIT分配单元。
DATABASE整个数据库。
锁的升级
说到锁的粒度和性能的关系。实际上,每个锁会占96字节的内存,如果有大量的小粒度锁,则会占据大量的内存。
比如,当我们选择几百行数据时(总共3W行),SQL Server会加对应行数的Key锁,但当所取得的行的数目增大时,比如说6000(表中总共30000多条数据),此时如果用6000个键锁的话,则会占用大约96*6000=600K左右的内存,所以为了平衡性能与并发之间的关系,SQL Server使用一个表锁来替代6000个key锁,这就是所谓的锁升级。
虽然使用一个表锁代替了6000个键锁,但是会影响到并发,我们对不在上述查询中行做更新,发现会造成阻塞.
锁的常见类型
排他锁(X锁): 和其它任何锁都不兼容,包括其它排他锁。排它锁用于数据修改,当资源上加了排他锁时,其他请求读取或修改这个资源的事务都会被阻塞,知道排他锁被释放为止。
更新锁(U锁) :U锁可以看作是S锁和X锁的结合,用于更新数据,更新数据时首先需要找到被更新的数据,此时可以理解为被查找的数据上了S锁。当找到需要修改的数据时,需要对被修改的资源上X锁。SQL Server通过U锁来避免死锁问题。因为S锁和S锁是兼容的,通过U锁和S锁兼容,来使得更新查找时并不影响数据查找,而U锁和U锁之间并不兼容,从而减少了死锁可能性。
意向锁(IS,IU,IX):意向锁与其说是锁,倒不如说更像一个指示器。在SQL Server中,资源是有层次的,一个表中可以包含N个页,而一个页中可以包含N个行。当我们在某一个行中加了锁时。可以理解成包含这个行的页,和表的一部分已经被锁定。当另一个查询需要锁定页或是表时,再一行行去看这个页和表中所包含的数据是否被锁定就有点太痛苦了。因此SQL Server锁定一个粒度比较低的资源时,会在其父资源上加上意向锁,告诉其他查询这个资源的某一部分已经上锁。比如,当我们更新一个表中的某一行时,其所在的页和表都会获得意向排他锁
死锁
指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
本文出自 “畅想天空” 博客,请务必保留此出处http://kinwar.blog.51cto.com/3723399/1401163
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。