TABLOCK和TABLOCKX之间的区别是什么
http://msdn.microsoft.com/en-us/library/ms187373.aspx声明TABLOCK是共享锁,而TABLOCKX是排他锁。第一个可能只是一种索引锁?共享锁的概念是什么?
发布于 2011-02-25 13:50:47
最大的不同是,TABLOCK将尝试获取“共享”锁和TABLOCKX排它锁。
如果您在事务中,并且获取了表上的排它锁,则EG:
SELECT 1 FROM TABLE WITH (TABLOCKX)
其他进程将无法获取表上的任何锁,这意味着所有试图与表对话的查询将被阻塞,直到事务提交为止。
TABLOCK仅获取共享锁,如果事务隔离为READ COMMITTED (缺省),则在执行语句后释放共享锁。如果您的隔离级别为is higher,例如:SERIALIZABLE,则共享锁将一直保持到事务结束。
共享锁是,嗯,共享的。这意味着两个事务可以同时从表中读取数据,如果它们都持有S或者是表上的锁(通过TABLOCK)。但是,如果transaction A持有表上的共享锁,则在释放所有共享锁之前,transaction B将无法获取独占锁。阅读有关哪些锁与哪些at msdn兼容的信息。
这两个提示都会导致数据库绕过更细粒度的锁(如行级锁或页面级锁)。原则上,更多的粒度锁允许更好的并发性。例如,一个事务可以同时从两个事务更新表中的第100行和第1000行(页锁会带来一些麻烦,但我们跳过这一步)。
一般来说,粒度锁是您想要的,但有时您可能想要减少db并发性,以提高特定操作的性能并消除死锁的可能性。
通常,您不会使用TABLOCK或TABLOCKX,除非您在某些边缘情况下绝对需要它。
发布于 2011-02-24 16:43:17
一个相当古老的article on mssqlcity试图解释锁的类型:
共享锁用于不更改或更新数据的操作,如SELECT语句。
在SQL Server打算修改页时使用更新锁,然后在实际进行更改之前将更新页锁提升为独占页锁。
排它锁用于数据修改操作,如更新、插入或删除。
它没有讨论的是Intent (它基本上是这些锁类型的修饰符)。意图(共享/独占)锁是在比实际锁更高的级别上持有的锁。因此,例如,如果您的事务在一行上有一个X锁,那么它在表级上也会有一个IX锁(这会阻止其他事务在表的更高级别上尝试获取不兼容的锁(例如,模式修改锁),直到您的事务完成或回滚)。
“共享”锁的概念非常简单-多个事务可以拥有同一资源的共享锁,而只有一个事务可以拥有独占锁,并且独占锁阻止任何事务获得或持有共享锁。
发布于 2017-01-06 08:24:35
这更像是一个TABLOCK不适用于我,而TABLOCKX适用于我的例子。
我有两个会话,这两个会话都使用默认的(已提交读)隔离级别:
会话1是一个显式事务,它将数据从链接服务器复制到数据库中的一组表,并需要几秒钟才能运行。例如,它删除了Session 2是一条insert语句的问题,该语句只是将行插入到Session 1不做更改的表中。例如,它插入答案。
(实际上,当会话1运行其事务时,有多个会话同时将多个记录插入到表中)。
会话1必须查询会话2插入的表,因为它无法删除依赖于会话2添加的条目的记录。示例:删除尚未回答的问题。
因此,当会话1正在执行并且会话2试图插入时,会话2每次都会在死锁中失败。
因此,会话1中的delete语句可能如下所示: DELETE tblA FROM tblQ LEFT JOIN tblX on ...左连接tblA a ON tblQ.Qid = tblA.Qid WHERE ...a.QId为NULL并且...
死锁似乎是由于会话2、3、4、5、...、n尝试插入tblA时查询tblA之间的争用引起的。
在我的例子中,我可以将会话1的事务的隔离级别更改为SERIALIZABLE。当我这样做的时候:事务管理器已经禁用了对远程/网络事务的支持。
因此,我可以按照这里接受的答案中的说明来解决这个问题:The transaction manager has disabled its support for remote/network transactions
但首先,我对将隔离级别更改为SERIALIZABLE感到不舒服--据推测,这会降低性能,并可能产生其他我没有考虑过的后果;b)我不明白为什么这样做会突然导致事务在链接的服务器上出现问题;c)我不知道启用网络访问可能会打开什么漏洞。
在一个非常大的事务中,似乎只有6个查询导致了问题。
所以,我读到了TABLOCK和TabLOCKX。
我对两者的区别不是很清楚,也不知道两者是否都行得通。但它看起来是这样的。首先,我尝试了TABLOCK,它似乎没有任何不同。竞争的会话产生了相同的死锁。然后我尝试了TABLOCKX,没有更多的死锁。
因此,在六个地方,我需要做的就是添加一个WITH (TABLOCKX)。
因此,会话1中的delete语句可能如下所示: DELETE tblA FROM tblQ q LEFT JOIN tblX x on ...在tblQ.Qid = tblA.Qid WHERE上左连接tblA a和(TABLOCKX) ...a.QId为NULL并且...
https://stackoverflow.com/questions/5102152
复制相似问题