Sql server TABLOCK vs TABLOCKX

Sql server TABLOCK vs TABLOCKX,sql-server,tsql,Sql Server,Tsql,TABLOCK和TABLOCKX之间的区别是什么?声明TABLOCK是共享锁,而TABLOCKX是独占锁。第一个可能只是某种索引锁吗?共享锁的概念是什么?解释锁的类型是一个相当古老的尝试: 共享锁用于不更改或更新数据的操作,如SELECT语句 当SQL Server打算修改页面时,会使用更新锁,稍后在实际进行更改之前,会将更新页面锁升级为独占页面锁 独占锁用于数据修改操作,如更新、插入或删除 它没有讨论的是意图(它基本上是这些锁类型的修饰符)。意向(共享/独占)锁是比实际锁级别更高的锁。因此,例

TABLOCK
TABLOCKX
之间的区别是什么?声明
TABLOCK
是共享锁,而
TABLOCKX
是独占锁。第一个可能只是某种索引锁吗?共享锁的概念是什么?

解释锁的类型是一个相当古老的尝试:

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

当SQL Server打算修改页面时,会使用更新锁,稍后在实际进行更改之前,会将更新页面锁升级为独占页面锁

独占锁用于数据修改操作,如更新、插入或删除

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



“共享”锁的概念非常简单——多个事务可以对同一资源拥有一个共享锁,而只有一个事务可能拥有一个排他锁,排他锁阻止任何事务获取或持有共享锁。

最大的区别是,
TABLOCK
将尝试获取“共享”锁锁,以及
TABLOCKX
独占锁

如果您在一个事务中,在一个表上获取了一个独占锁,例如:

使用(TABLOCKX)从表格中选择1

没有其他进程能够抓取表上的任何锁,这意味着在事务提交之前,所有试图与表对话的查询都将被阻止

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


共享锁是共享的。这意味着如果两个事务都持有表上的S或IS锁(通过
TABLOCK
),则它们可以同时从表中读取数据。但是,如果
事务A
持有表上的共享锁,
事务B
将无法获取独占锁,直到释放所有共享锁。了解哪些锁与哪些兼容


这两个提示都会导致db绕过更细粒度的锁(如行或页级锁)。原则上,更细粒度的锁允许更好的并发性。例如,一个事务可以同时从两个事务中更新表中的第100行和第1000行(页面锁定很棘手,但我们可以跳过这一点)

一般来说,粒度锁是您想要的,但有时您可能希望降低数据库并发性以提高特定操作的性能并消除死锁的可能性


一般来说,您不会使用
TABLOCK
TABLOCKX
,除非您在某些边缘情况下绝对需要它。

这是TABLOCK不适用于我而TABLOCKX适用于我的更多示例

我有两个会话,都使用默认(读提交)隔离级别:

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

(实际上,当会话1运行其事务时,有多个会话同时将多条记录插入表中)

会话1必须查询会话2插入的表,因为它无法删除依赖于会话2添加的条目的记录。[示例:删除尚未回答的问题]

因此,当会话1正在执行且会话2尝试插入时,会话2每次都会在死锁中丢失

因此,会话1中的delete语句可能如下所示: 从tblQ中删除tblA左连接tblX在。。。 在tblQ.Qid=tblA.Qid上左连接tblA a 哪里a、 QId为NULL并且

死锁似乎是由于在会话2、[3、4、5、…,n]尝试插入tblA时,查询tblA之间的争用引起的

在我的例子中,我可以将会话1事务的隔离级别更改为可序列化。当我这样做时:事务管理器已禁用其对远程/网络事务的支持

因此,我可以按照这里公认答案中的说明来绕过它:

但是a)我一开始对将隔离级别更改为可序列化感到不舒服-可能会降低性能,并可能产生我没有考虑过的其他后果,b)不理解为什么这样做会突然导致事务在链接服务器之间出现问题,c)不知道启用网络访问可能会打开哪些漏洞

在一个非常大的事务中,似乎只有6个查询造成了问题

所以,我读了关于TABLOCK和TabLOCKX的书

我并不十分清楚两者之间的区别,也不知道两者是否可行。但似乎是这样。首先我尝试了TABLOCK,但似乎没有任何区别。竞争会话产生了相同的死锁。然后我尝试了TABLOCKX,没有更多的死锁

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

因此,会话1中的delete语句可能如下所示: 从tblQ中删除tblA左连接tblX在。。。 左乔伊