SQL Server中的事务是否默认锁定语句中的所有表



假设我有一个T-SQL语句,如下所示:

BEGIN TRAN
UPDATE dbo.TableA 
...
...
...
DELETE FROM dbo.TableB
COMMIT TRAN

假设TableA的更新需要一些时间。

默认情况下,SQL Server会锁定TableB直到事务完成吗?这是否意味着在更新过程中你不能读写它?

简短回答:否和否

长话短说:事实上,这是一个很好的问题,因为它深入到了交易概念和引擎是如何工作的,但我想一个完整的答案可能会占据一本好书的大部分章节,超出了本网站的范围。

首先请记住,引擎可以在几种隔离模式下工作:快照、读取提交等。我可以推荐对该主题进行良好的研究(这可能需要几天时间(。

第二个,引擎有粒度级别,会尝试使用"最小"的粒度级别,但可以根据需要升级,这取决于许多因素,例如:"此操作是否需要页面拆分?">

第三个BEGINCOMMITROLLBACK更多地以"信号量"的方式工作,标记如何将更改从"内存"分阶段转移到"磁盘"。它比它复杂得多,这就是我使用引号的原因。

也就是说,"默认事务"将在读提交隔离模式中使用行粒度。没有说明如何以某种方式发放锁。这取决于外键、触发器、表的更改量等。

TLDR:这取决于许多特定于您场景的小细节。找到答案的最好方法是通过测试。

根据@Jeroen Mostert、@marc_s和@Cato对该问题的评论,由于没有"where"子句,您在表A和表B上的锁可能会升级为表独占锁。如果是这样,则来自不同连接的其他读取和写入操作可能会根据其事务隔离级别受到影响,直到该事务结束。

此外,锁是按需创建的;这意味着查询首先在表a上加一个锁,在执行更新操作之后,它在表B上加另一个锁。

最新更新