首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TABLOCK与TABLOCKX

TABLOCK与TABLOCKX
EN

Stack Overflow用户
提问于 2011-02-24 16:31:48
回答 3查看 151.8K关注 0票数 79

TABLOCKTABLOCKX之间的区别是什么

http://msdn.microsoft.com/en-us/library/ms187373.aspx声明TABLOCK是共享锁,而TABLOCKX是排他锁。第一个可能只是一种索引锁?共享锁的概念是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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并发性,以提高特定操作的性能并消除死锁的可能性。

通常,您不会使用TABLOCKTABLOCKX,除非您在某些边缘情况下绝对需要它。

票数 109
EN

Stack Overflow用户

发布于 2011-02-24 16:43:17

一个相当古老的article on mssqlcity试图解释锁的类型:

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

在SQL Server打算修改页时使用更新锁,然后在实际进行更改之前将更新页锁提升为独占页锁。

排它锁用于数据修改操作,如更新、插入或删除。

它没有讨论的是Intent (它基本上是这些锁类型的修饰符)。意图(共享/独占)锁是在比实际锁更高的级别上持有的锁。因此,例如,如果您的事务在一行上有一个X锁,那么它在表级上也会有一个IX锁(这会阻止其他事务在表的更高级别上尝试获取不兼容的锁(例如,模式修改锁),直到您的事务完成或回滚)。

“共享”锁的概念非常简单-多个事务可以拥有同一资源的共享锁,而只有一个事务可以拥有独占锁,并且独占锁阻止任何事务获得或持有共享锁。

票数 5
EN

Stack Overflow用户

发布于 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并且...

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5102152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档