SQL Server批量插入时表锁定问题

3

以下是示例查询,请考虑A

INSERT INTO Target (Col1,Col2,Col3,Col4) ----------------Statement#1
Select A.Col1,B.Col2,A.Col3,C.Col4       ----------------Statement#2
FROM A WITH(NOLOCK) INNER JOIN B WITH(NOLOCK)
    ON A.Id = B.ID
    LEFT JOIN C WITH NOLOCK
    ON C.Id = B.ID
Where A.Id = 11

当表格被锁定的阶段是什么时候[独占锁?],SQL将如何执行查询?

  1. 根据连接和where子句从表A、B和C中获取结果。
  2. 在准备好的结果上,开始向表中插入数据,并同时对表进行加锁。

因此,即使使用INSERT INTO与SELECT,只有在实际写入页面表格时才会锁定表格,而不是在选择时。

2个回答

2

这两个步骤是查询执行的逻辑步骤。SQL Server在物理层面上能够做些什么,则是另一回事了。此刻:

INSERT INTO Target (Col1,Col2,Col3,Col4) ----------------Statement#1
Select A.Col1,B.Col2,A.Col3,C.Col4       ----------------Statement#2
FROM A WITH(NOLOCK) INNER JOIN B WITH(NOLOCK)
    ON A.Id = B.ID
    LEFT JOIN C WITH NOLOCK
    ON C.Id = B.ID
Where A.Id = 11

对于每个输出记录(参见SELECT子句),它会在目标表中的RIDKEY上获取一个X锁(堆使用RID/聚集索引使用KEY),并插入该记录。对于每个输出记录,都会重复执行此步骤。因此,它不会从源表中读取所有记录,并且仅在此步骤之后开始将记录插入目标表。由于源表上有NOLOCK表提示,因此它只会在这些表上获取Sch-S(模式稳定性)锁。
如果您想在目标表上获取X锁,则可以使用:
INSERT INTO Target WITH(TABLOCKX) (Col1,Col2,Col3,Col4)
SELECT ...

如果您想要最小化记录的插入操作,请阅读这篇文章


好的,这是逐行获取和插入吗?这就是你想说的吗?另外,如果选择查询需要500毫秒才能获得结果,目标表上的锁定持续时间将是多久? - Hi10
1&2) 基本上是的。3)從獲取 X 鎖的時刻開始到交易結束(如果您具有顯式交易:COMMIT/ROLLBACK),或者到語句執行結束(自動提交交易)。如果沒有 TABLOCKX,則在將每個記錄插入目標表之前,會在記錄級別(RID/KEY)獲取 X 鎖。使用 TABLOCKX 暗示後,在語句執行開始時只需一次即可在表級別上獲取 X 鎖。 - Bogdan Sahlean
1
感谢您的回答。 - Hi10

0

我没有指定任何时间锁,我的问题是当检测到插入语句或实际插入发生时,会立即放置什么时间锁? - Hi10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接