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

Sql server SQL Server中的事务是否默认锁定语句中的所有表?,sql-server,Sql Server,假设我有这样一个T-SQL语句: BEGIN TRAN UPDATE dbo.TableA ... ... ... DELETE FROM dbo.TableB COMMIT TRAN 假设TableA上的更新需要一些时间 默认情况下,SQL Server会锁定TableB直到事务完成吗?这是否意味着在更新过程中您不能读写它?根据@Jeroen Mostert、@marc_s和@Cato在问题下的评论,您在TableA和TableB上的锁可能会升

假设我有这样一个T-SQL语句:

BEGIN TRAN

    UPDATE dbo.TableA 
    ...
    ...
    ...

    DELETE FROM dbo.TableB

COMMIT TRAN
假设TableA上的更新需要一些时间


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

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


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

简短回答:否和否

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

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

,引擎具有粒度级别,将尝试使用“最小”粒度级别,但可以根据需要升级,这取决于许多因素,例如:“此操作是否需要拆分页面?”

Third
BEGIN
COMMIT
ROLLBACK
以“信号量”的方式工作,标记从“内存”到“磁盘”的更改是如何分阶段进行的。它比它复杂得多,这就是为什么我使用引号

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


TLDR:这取决于许多特定于您的场景的次要细节。最好的方法是通过测试。

T-SQL是一种严格的顺序语言。在对
TableA
进行更新之前,
TableB
甚至不会发生任何事情。事务不会将服务器提交到“时间点快照”或类似于“时间点快照”的文件,这类文件始终是逐表提交的。此外,默认情况下,SQL Server将始终使用行级锁定—它不仅锁定整个表—只锁定受操作影响的那些单独的行。一个常见的误解是,
BEGIN-TRAN
/
COMMIT-TRAN
形成某种语法块,作为一个整体进行解析和执行。它们不是,它们是独立的陈述。(如果您从未发出
COMMIT-TRAN
,事务将一直挂起,直到您关闭连接并隐式回滚为止。)服务器将接收所有的语句。有一个单独的
BEGIN-ATOMIC
语法将块视为一个完整的部分,但这只用于内存中的操作。@marc_s:我认为行级锁可以自动“升级”到页面级和表级锁,只要它认为合适——因此工程师可能会期望某类记录被其他进程“解锁”,但这并不能保证,可能会升级到页面或表格locking@Cato:是,情况就是这样-如果一个事务中有5000多个行级锁,SQL Server将执行锁升级到表级(而不是页面级)否-SQL Server仍将使用行级锁-只是缺少
WHERE
子句不会改变这一点!如果受单个事务影响的行数超过5000行,SQL Server会将行级锁升级为表级锁感谢@marc_s的澄清。我已经相应地更新了我的答案。我想是我的英语不好。