Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 删除语句锁定表_Sql_Sql Server - Fatal编程技术网

Sql 删除语句锁定表

Sql 删除语句锁定表,sql,sql-server,Sql,Sql Server,我在一个不断成行增长的表上运行清理作业(每小时一次)。该作业运行了大约一周,没有任何问题。今天我看到作业开始锁定整个桌子 这是预期的行为吗?是否在需要删除的特定行数之后,它会锁定整个表,而不是只锁定需要删除的特定行 提前谢谢 如果查询影响同一个表中的5000行或更多行,则该表在操作期间会被锁定。这是标准的SQL Server行为。基本上,每次删除都会导致该行上的锁,同一个表上的每5000行锁会导致锁从一行升级到另一个表。当您更新/删除一行时,它会被锁定(目前为止很容易),当有许多行需要修改时,每

我在一个不断成行增长的表上运行清理作业(每小时一次)。该作业运行了大约一周,没有任何问题。今天我看到作业开始锁定整个桌子

这是预期的行为吗?是否在需要删除的特定行数之后,它会锁定整个表,而不是只锁定需要删除的特定行


提前谢谢

如果查询影响同一个表中的5000行或更多行,则该表在操作期间会被锁定。这是标准的SQL Server行为。基本上,每次删除都会导致该行上的锁,同一个表上的每5000行锁会导致锁从一行升级到另一个表。

当您更新/删除一行时,它会被锁定(目前为止很容易),当有许多行需要修改时,每个行都会被锁定,直到某个时间点,正如jean所提到的,当DBMS“决定”切换到“锁定整个表”时,这取决于DBMS的许多(通常是可伸缩的)参数,并且(通常)会获得更好的性能

但这有一个不好的地方:出现“死锁”的机会增加(我曾经遇到过mor的问题,或者不到100%的机会),因为当DBMS切换到“锁表”时,它必须等待该表上其他任务的锁,但它自己(或你的UOW)allready已经锁定了几千行了

为了避免这种情况,有时如果您稍微“推”一下DBMS并提前锁定整个表(以独占模式),这会有所帮助。如果UPDATE/DELETE-it自修改足够多的行以发生表锁定,但在world上仍然足够快,这会有所帮助—这就是您的环境中“足够快”的含义


另一种避免这种情况的方法是,如果您不依赖UOW(回滚),则每个查询只删除/更新部分,但这通常不是清理的问题(如果回滚,则也是下一次清理的一部分),如何做到这一点取决于您的环境

一种可能性是,您需要为搜索表中要删除的行所依据的列编制索引。如果没有索引,那么SQLServer在搜索要删除的行时将获得更多的锁

我强烈建议删除循环中的小块行。正如其他人所指出的,如果您试图一次删除5000多行,SQL Server将把行锁升级为表锁。一次删除更少的记录(比如1000条)可以避免锁定整个表。您的作业可以继续循环删除,直到完成为止

循环删除的伪代码如下所示:

declare @MoreRowsToDelete bit
set @MoreRowsToDelete = 1
while @MoreRowsToDelete = 1
begin
    delete top (1000) MyTable from MyTable where MyColumn = SomeCriteria
    if not exists (select top 1 * from MyTable where MyColumn = SomeCriteria)
        set @MoreRowsToDelete = 0
end
或者,您可以查看
@@ROWCOUNT
并使用
readpass
提示来避免锁定行:

declare @RowCount int
set @RowCount = 1 -- priming the loop
while @RowCount > 0
begin
    delete top (1000) MyTable from MyTable with (readpast) where MyColumn = SomeCriteria
    set @RowCount = @@ROWCOUNT
end

请注意,锁升级阈值取决于其他因素,如并发活动。如果您经常有太多的活动,即使是1000次删除也会升级为表锁,那么您可以立即减少删除的行数。

看看文章,行的缩放取决于很多因素,如页面大小、填充因子等,而不仅仅是行数。