TABLOCK与TABLOCKX

TABLOCKTABLOCKX之间有什么区别http://msdn.microsoft.com/en-us/library/ms187373.aspx指出TABLOCK是共享锁,而TABLOCKX是排他锁。 第一个也许只是一个索引锁的种类? 共享锁的概念是什么?

差别很大, TABLOCK将尝试抓取“共享”锁和TABLOCKX独占锁。

如果您正在交易中,并且您在桌子上抓取排他锁,那么EG:

SELECT 1 FROM TABLE WITH (TABLOCKX)

没有其他进程将能够获取表上的任何锁,这意味着试图与表交谈的所有查询将被阻塞,直到事务提交。

TABLOCK只抓取共享锁,如果事务隔离是READ COMMITTED (默认),则在语句执行后释放共享锁。 如果您的隔离级别较高 ,例如: SERIALIZABLE ,共享锁一直保持到事务结束。


共享锁,嗯,共享。 含义2事务可以同时从表中读取数据(如果它们都在表上持有S或IS锁)(通过TABLOCK )。 但是,如果transaction A持有表上的共享锁,那么transaction B将无法获取排它锁,直到释放所有共享锁。 阅读哪些锁与msdn兼容。


这两个提示导致数据库绕过采取更多的粒度锁(如行或页面级锁)。 原则上,更细粒度的锁允许您更好的并发性。 例如,一个事务可以更新表中的第100行,同时更新另一行1000, 同时从两个事务处理(页面locking变得棘手,但让我们跳过)。

一般来说,粒度锁是你想要的,但有时你可能想要减less数据库并发性来提高特定操​​作的性能,并消除死锁的可能性。

一般来说,除非你绝对需要它,否则不会使用TABLOCKTABLOCKX

很多关于mssqlcity的文章都试图解释锁的types:

共享锁用于不更改或更新数据的操作,如SELECT语句。

当SQL Server打算修改一个页面时使用更新locking,并且稍后在实际进行更改之前将更新页面locking提升为独占页面locking。

独占锁用于数据修改操作,如UPDATE,INSERT或DELETE。

它没有讨论的是Intent(它基本上是这些锁types的修饰符)。 意图(共享/专有)锁是锁在比真实锁更高的级别。 所以,举例来说,如果你的事务在一行上有一个X锁,那它也将在表级别有一个IX锁(这会阻止其他事务试图获得表上较高级别的不兼容锁(例如一个模式修改locking),直到您的事务完成或回滚)。


“共享”一个锁的概念非常简单 – 多个事务可以为同一个资源拥有一个共享锁,而只有一个事务可以有一个独占锁,排他锁则排除任何事务获取或持有共享锁。

这更像是TABLOCK不适合我和TABLOCKX的一个例子。

我有2个会话,都使用默认(READ COMMITTED)隔离级别:

会话1是一个显式事务,它将数据从链接服务器复制到数据库中的一组表中,并且需要几秒钟的时间才能运行。 [例如,删除问题]会话2是一个插入语句,只是将行插入到会话1不会更改的表中。 [例如,插入答案]。

(实际上,会话1正在运行其事务的同时,会有多个会话向表中插入多个logging)。

会话1必须查询会话2插入的表格,因为它不能删除依赖于会话2添加的条目的logging。[示例:删除未被回答的问题]。

因此,在会话1执行和会话2尝试插入的同时,会话2每次都会陷入僵局。

因此,会话1中的删除语句可能如下所示:DELETE tblA FROM tblQ LEFT JOIN tblX on … LEFT JOIN tblA a ON tblQ.Qid = tblA.Qid WHERE … a.QId IS NULL …

僵局似乎是由于查询tblA而导致的,而会话2 [3,4,5,…,n]试图插入到tblA中。

在我的情况下,我可以将Session 1的事务的隔离级别改为SERIALIZABLE。 当我这样做:事务pipe理器已经禁用了对远程/networking事务的支持。

所以,我可以按照接受的答案中的指示来避开它: 事务pipe理器已经禁用了对远程/networking事务的支持

但是a)我并不习惯将隔离级别改为SERIALIZABLE,这应该会降低性能,并且可能会有其他后果,我没有考虑到,b)不明白为什么突然这样做会导致交易跨链接服务器工作的问题,以及c)不知道通过启用networking访问可能会打开什么样的漏洞。

在一个非常大的交易中似乎只有6个查询正在引起麻烦。

所以,我读了TABLOCK和TabLOCKX。

我对这个分歧并不是很清楚,也不知道是否会有效果。 但似乎是这样。 首先,我尝试了TABLOCK,并且没有任何区别。 竞争会话产生了相同的死锁。 然后我尝试了TABLOCKX,没有更多的死锁。

所以,在六个地方,我所需要做的就是添加一个WITH(TABLOCKX)。

因此,会话1中的删除语句可能如下所示:DELETE tblA FROM tblQ q LEFT JOIN tblX x on … LEFT JOIN tblA WITH(TABLOCKX)ON tblQ.Qid = tblA.Qid WHERE … a.QId IS NULL和…