【问题标题】:SQL Server Locks entire table althrough it isn't neededSQL Server 锁定整个表,尽管它不是必需的
【发布时间】:2026-02-07 16:30:01
【问题描述】:

我正在使用以下代码从 SQL Server 表中删除行

DELETE FROM MyTable WHERE YEAR(CreationDate) <= 2013

并且(因为表很大 50GB)在执行此查询时我正在执行 INSERT:

INSERT INTO MyTable(...., CreationDate) VALUES(...., '2014-02-24') 

(不要介意日期格式。这只是一个示例。)

但是,INSERT 会一直等到 DELETE 操作完成,尽管从逻辑上讲,SQL Server 可以执行 INSERT,因为它不会影响 DELETE 操作的结果。

有没有办法避免这种锁定?

【问题讨论】:

  • 我不记得细节了,但是有一个阈值,超过这个阈值 MSSQL 决定锁定整个表。这是一种优化,另一种方法是锁定单个索引块,这可能会更慢。

标签: sql sql-server transactions locking


【解决方案1】:

您至少可以尝试通过使搜索条件 SARGable 来帮助服务器:

DELETE FROM MyTable WHERE CreationDate < '20140101'

假设CreationDate 上有一个索引,它可能现在可以使用它了。

【讨论】:

  • 同意,由于 where 子句,它可能不得不进行表扫描。开启执行计划,看看delete是否在做表扫描。
  • 基本上就是这样。永远不要评估过滤器字段 - 这会杀死任何使用的索引。用于大型数据库的 Sql 101。在这种特殊情况下,转换是微不足道的(如您所示),并且将确保可以使用索引 - 如果从成本方面自然而然的话,这是查询优化器的决定。
  • 我按照您的建议修改了查询,实际上在查询执行计划中它说查询将使用索引。但是问题仍然存在:删除确实花费了太多时间(可能是因为要同步表的许多索引)并且由于表被锁定,因此没有执行插入。
【解决方案2】:

我个人会选择类似于 Damien 的东西......

Delete From MyTable Where CreationDate='2013'

Insert Into MyTable (Creation Date ) Values ( 2014-02-24 ) Where CreationDate=''

(我希望''将是刚刚删除的记录)

这将同时执行删除和插入,我认为您个人只是语法错误。

【讨论】:

    【解决方案3】:

    尝试开启trace,可以发现死锁情况

    【讨论】:

      最近更新 更多