了解SQL Server中的SIX锁定

时间:2013-06-26 12:25:45

标签: sql-server tsql locking deadlock

有人可以解释一下进程如何获取页面上的SIX锁定吗?我的死锁图xml文件我看到在 RC隔离级别下运行的进程(在死锁时执行select语句)在页面上保持SIX锁定。

这意味着什么以及如何获得锁定? 根据我从http://msdn.microsoft.com/en-us/library/aa213039%28v=sql.80%29.aspx SIX获得的锁保护S - 锁定所有资源,并在层次结构中较低的某些资源上锁定IX

我的情况是IX - 锁定行? IX - 锁可以放在一行吗? (我觉得不是)。我很困惑。

另一件事是我希望有几个X - 锁定行而不是S - 完全锁定(因为 IL ReadCommited )。如果我只在前面的语句中插入了几条记录,为什么我用SIX锁定了整个页面?

起来!

1 个答案:

答案 0 :(得分:3)

通过Sebastian Meine来回答dba:

  

要回答我必须绕道而行,所以请耐心等待。   如果两个会话锁定同一资源,则SQL Server会检查锁兼容性映射,如果第二个请求与第一个请求不兼容,则第二个会话必须等待。有三种锁定类型“S”hared,“U”pdate和e“X”cluster。 S锁用于从资源读取,并且X锁用于写入资源。 S锁彼此兼容,X锁与其他任何东西都不兼容。 U锁是一种混合,在某些情况下用于防止死锁。

     

现在,SQL Server可以在几个级别上进行锁定:表,分区,页面和行。因此,如果会话1采用表锁并且会话2在表的一行上采用不兼容的锁,则这两个锁不在同一资源上,并且SQL Server将不会检测到冲突。为了防止这种情况,SQL Server始终开始在表级别上锁定并沿着层次结构向下工作。现在页面和行锁的点是更高的并发性,因此如果一个会话想要写入一行而另一个会话想要写入另一行,则它们不应该相互阻塞。如果一个会话除了对一行进行锁定之外还必须对表进行相同的锁定,那么这种优势就会消失。因此,会话不是在表上采用独占锁(X),而是请求一个打算独占锁(IX)。此锁与其他打算锁兼容,但与其他“实际”锁不兼容。因此,另一个会话也可以在同一个表上进行打算独占锁定。意图排他锁说,会话打算对较低级别的资源进行独占锁定。如果预期的锁是行锁,则在页面级别上也会发生相同的情况,因此在完成所有操作后,会话在表上和其中一个页面上有一个IX锁,并且该页中的一行上有一个X锁。这也意味着,您永远不会在行上找到意图锁定,因为行是锁定层次结构中的最低级别。

     

在某些情况下,会话在表或页面上持有S锁。如果会话现在(在同一个事务中)请求对同一个表中的行进行X锁定,则首先必须对表/页面进行IX锁定。但是,会话只能在任何给定资源上保留一个锁。因此,要采用IX锁,它必须释放可能不需要的S锁,因此SQL Server提供了一个组合:SIX。

     

您有页面锁定的原因是SQL Server有时会决定锁定页面而不是锁定每一行更好。如果已经在会话之间进行了很多锁定,那么这种情况经常发生,但也可能有许多其他原因。

     

到目前为止的理论。

     

现在,在您的情况下,SIX锁由三个表连接选择查询保持。除非您明确告诉它(例如,使用XLOCK提示),否则select永远不会采用任何类型的非共享锁的锁。这样的提示在输入缓冲区中是不可见的,因此我假设IX部分是此连接上最后一批的剩余部分。如果您正在使用连接池并忘记清除所有打开的事务,那么这样的锁可能永远存在。但是排除故障也很困难。

     

你可以先运行一个XENvent会话,将OPEN TRAN与COMMIT配对,看看你是否能找到那种罪魁祸首。


来源:https://dba.stackexchange.com/questions/45284/understanding-six-lock-in-microsoft-sql-server