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