Na produkčním serveru se pravidelně při větší update dat začalo objevovat následující chybové hlášení: ‘Error 601: Could not continue scan with NOLOCK due to data movement’. Produkční server běží na SQL Server 2008R2 SP1 Standard edition. Po delší hledání se podařilo najít popis chyby v tomto KB: http://support.microsoft.com/kb/960770/en-us.
V našem konkrétním příkladě se chyba objevovala v kódu, který využíval následující logiku:
DECLARE @TempTable TABLE (...)
INSERT INTO @TempTable
SELECT * FROM ....
INSERT INTO @TempTable
select *
from ( select distinct * from @TempTable ) tt
cross join dbo.TableA a
where
a.Col1 >= 1
Problematickou operací je zde vkládání do @TempTable ve stejném okamžiku, kdy se z tabulky čte. Zápis do tabulky způsobí realokaci stránek, které mají být teprve přečteny a v okamžiku čtení se již nenacházejí na svém místě.
Řešením je intuitivní přepsání kódu tak, že data se nejprve vloží do dočasné tabulky #Distinct a tato tabulka je následně využita k získání dat pro vložení do @TempTable. Tím se předejde realokaci stránek a výše zmíněné chybě.
DECLARE @TempTable TABLE (...)
INSERT INTO @TempTable
SELECT * FROM ....
SELECT DISTINCT *
INTO #Distinct
FROM @TempTable
INSERT INTO @TempTable
SELECT *
FROM #Distinct tt
cross join dbo.TableA a
WHERE
a.Col1 >= 1
