为什么这个查询块会插入?

时间:2011-11-23 20:26:02

标签: sql sql-server-2008

有一个小时运行的进程必须插入​​到table1中,但是当下面的查询运行时,插入被阻塞。有谁能解释为什么?我意识到锁定提示就是这样,提示和SQL可能会选择忽略它们。 table1有300米行,我需要更新ColumnA中的值。我正在以块为单位来帮助进行回滚,以防止进程停止,因此是while循环。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
go

declare @start bigint
declare @end bigint
declare @max bigint
declare @step int

set @step = 50000
set @start = 17953095
set @end = @start + @step
set @max = @start + 2000000

while ( @end < @max )
begin

waitfor delay '00:00:10'

begin transaction

update [table1] with (ROWLOCK)
set [table1].[ColumnA] = [table2].[ColumnA]
from [table2] (nolock)
where [table2].[ColumnB] = [table1].[ColumnB] 
and [table1].ID >= @start 
and [table1].ID <  @end

commit transaction

print @end

if @end >= @max 
begin
    break
end

set @start = @end
set @end = @end + @step

end

print @end

我可以用其他方式执行此操作,因此它不会阻止插入或其他更新吗?除了上面的查询之外,没有其他任何东西需要使用ColumnA。

1 个答案:

答案 0 :(得分:2)

您可以尝试使用较小的批量。当超过某个阈值时,SQL Server会根据MSDN

将行锁直接升级为表锁
  

数据库引擎不会将行或键范围锁升级到页面   锁,但将它们直接升级为表锁。   
...
  ...
  未禁用锁定升级时会触发锁定升级   该表使用ALTER TABLE SET LOCK_ESCALATION选项,和   当存在以下任一条件时:

     

单个Transact-SQL语句在a上获取至少5,000个锁   单个非分区表或索引。

     

单个Transact-SQL语句在a上获取至少5,000个锁   分区表的单个分区和ALTER TABLE SET   LOCK_ESCALATION选项设置为AUTO。

     

数据库引擎实例中的锁数超过   内存或配置阈值。

     

如果由于锁冲突而无法升级锁,则数据库   引擎定期在每1250个新锁上触发锁升级   获得的。

您当前的批量大小为50,000,远远超过该阈值。

要考虑的另一件事是你是否有合适的指数来适应你的WHERE条款 - 确保尽可能最佳。