有一个小时运行的进程必须插入到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。
答案 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条款 - 确保尽可能最佳。