实验前先介绍下 sp_lock
SP_LOCK报告有关锁的信息。
spid | dbid | ObjId | IndId | Type | Resource | Mode | Status |
51 | 5 | 0 | 0 | DB | S | GRANT |
spid:进程id
dbid:数据库id
objid:数据库内对象id
IndId: 持有锁的索引的标识号。
type:锁的资源类型
RID = 表中单个行的锁,由行标识符 (RID) 标识。
|
KEY = 索引内保护可串行事务中一系列键的锁。 |
PAG = 数据页或索引页的锁。 |
EXT = 对某区的锁。 |
TAB = 整个表(包括所有数据和索引)的锁。 |
DB = 数据库的锁。 |
FIL = 数据库文件的锁。 |
APP = 指定的应用程序资源的锁。 |
MD = 元数据或目录信息的锁。 |
HBT = 堆或 B 树索引的锁。在 SQL Server 中此信息不完整。 |
AU = 分配单元的锁。在 SQL Server 中此信息不完整。 |
Resource:syslockinfo.restext 中的值对应的锁资源的位置。
Mode:请求的锁的类型
主要的有:
共享锁 (S) 用于不更改或不更新数据的操作(只读操作),如SELECT语句。
更新锁 (U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
排它锁 (X) 用于数据修改操作,例如INSERT、UPDATE或DELETE。确保不会同时对同一资源进行多重更新。
意向锁 (I+_) 用于建立锁的层次结构。意向锁的类型为:意向共享(IS)、意向排它(IX)以及与意向排它共享(SIX)。
架构锁 在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改(Sch-M)和架构稳定性(Sch-S)。
大容量更新锁 (BU)向表中大容量复制数据并指定了TABLOCK提示时使用。
详细的:
Sch-S = 架构稳定性。确保在任何会话持有对架构元素(例如表或索引)的架构稳定性锁时,不删除该架构元素。
Sch-M = 架构修改。必须由要更改指定资源架构的任何会话持有。确保没有其他会话正在引用所指示的对象。
S = 共享。授予持有锁的会话对资源的共享访问权限。
U = 更新。指示对最终可能更新的资源获取的更新锁。用于防止一种常见的死锁,这种死锁在多个会话锁定资源以便稍后对资源进行更新时发生。
X = 排他。授予持有锁的会话对资源的独占访问权限。
IS = 意向共享。指示有意将 S 锁放置在锁层次结构中的某个从属资源上。
IU = 意向更新。指示有意将 U 锁放置在锁层次结构中的某个从属资源上。
IX = 意向排他。指示有意将 X 锁放置在锁层次结构中的某个从属资源上。
SIU = 共享意向更新。指示对有意在锁层次结构中的从属资源上获取更新锁的资源进行共享访问。
SIX = 共享意向排他。指示对有意在锁层次结构中的从属资源上获取排他锁的资源进行共享访问。
UIX = 更新意向排他。指示对有意在锁层次结构中的从属资源上获取排他锁的资源持有的更新锁。
BU = 大容量更新。用于大容量操作。
RangeS_S = 共享键范围和共享资源锁。指示可串行范围扫描。
RangeS_U = 共享键范围和更新资源锁。指示可串行更新扫描。
RangeI_N = 插入键范围和 Null 资源锁。用于在将新键插入索引前测试范围。
RangeI_S = 键范围转换锁。由 RangeI_N 和 S 锁的重叠创建。
RangeI_U = 由 RangeI_N 和 U 锁的重叠创建的键范围转换锁。
RangeI_X = 由 RangeI_N 和 X 锁的重叠创建的键范围转换锁。
RangeX_S = 由 RangeI_N 和 RangeS_S 锁的重叠创建的键范围转换锁。
RangeX_U = 由 RangeI_N 和 RangeS_U 锁的重叠创建的键范围转换锁。
RangeX_X = 排他键范围和排他资源锁。这是在更新范围中的键时使用的转换锁。
status:
CNVRT:锁正在从另一种模式进行转换,但是转换被另一个持有锁(模式相冲突)的进程阻塞。
GRANT:已获取锁。
WAIT:锁被另一个持有锁(模式相冲突)的进程阻塞。
实例: 开两个会话。
----------------------------------------实验1
会话1:执行
begin tran
update a set a.exce_count=2 from [dbo].[monitor] a where a.AVG_Num='20161007'
不提交显示影响两行
另外一个会话2 运行:sp_lock
ObjId IndId Type Resource Mode
338100245 0 PAG 1:180 IX
338100245 0 PAG 1:178 IX
338100245 0 RID 1:178:0 X
338100245 0 RID 1:180:2 X
338100245 0 TAB IX
显示产生5 个锁,两个页 的意向排他,一个表的意向排他 两个行级 的排他锁。
在会话2 执行 查询语句
select * from [dbo].[monitor] a where a.AVG_Num='20161007'
语句执行会被阻塞
开会话3 执行:sp_lock
ObjId IndId Type Resource Mode Status
338100245 0 TAB IS GRANT
338100245 0 RID 1:178:0 S WAIT
338100245 0 PAG 1:178 IS GRANT
显示会话2 状态为等待 同时生成共享和意向共享锁
如果提交会话一阻塞通过,现在先不提交。
停止会话2,在执行
select * from [dbo].[monitor] a with( nolock ) where a.AVG_Num='20161007'
执行成功不会产生共享锁, 但显示的是脏数据。
提交会话1
注:删除语句 也上上面的例子类似
--------------------------------------------实验2
会话1执行:
begin tran
alter table [dbo].[monitor] alter column avg_num int
产生 意向排他 排他 共享锁 以及架构锁
0 0 DB [DDL] S
3 1 KEY (5aacc16bdc52) X
0 0 MD 7(38:0:0) Sch-S
34 1 KEY (7c7a938bc17e) X
0 0 DB S
3 0 TAB IX
34 0 TAB IX
41 0 TAB IX
338100245 0 TAB Sch-M
41 1 KEY (03e0a83a982c) X
会话2执行:
select * from [dbo].[monitor] a with( nolock ) where a.AVG_Num='20161007'
执行不通过。
会话3执行:sp_lock
显示会话2 锁为架构稳定锁。注意查询语句是加了with(nolock) 的
ObjId IndId Type Resource Mode Status
338100245 0 TAB Sch-S WAIT
提交会话1 ,会话2执行成功。
平时查找问题,需要注意锁的类型 以及锁的状态