Recebo essa mensagem de erro ocasionalmente quando executo um procedimento armazenado que extrai informações de vários servidores vinculados e agrega os dados. Parece com o que tenho abaixo.
DECLARE Cur CURSOR FOR SELECT name FROM sys.servers WHERE is_linked = 1 AND (@Environments IS NULL OR name IN (SELECT Item FROM clrStringSplit(@Environments, ',')))
OPEN cur
FETCH NEXT FROM cur INTO @Environment
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
SET @Query = '
EXEC ' + @Environment + '.db.dashboard.storedproc ''' + CAST(@StartDate AS VARCHAR(10)) + ''', ''' + CAST(@EndDate AS VARCHAR(10)) + ''''
INSERT INTO #Table (Environment, Column1, Column2, Column3, Column4, Column5, Column6, Column7)
EXEC(@Query)
END TRY
BEGIN CATCH
PRINT 'There was an error trying to query against ' + @Environment
PRINT ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM cur INTO @Environment
END
O procedimento armazenado que ele chama em cada servidor é exatamente o mesmo em cada um e é uma instrução select básica que extrai das tabelas sob o esquema dbo. O erro "aleatoriamente" será exibido com a mensagem "Não foi possível concluir a operação do cursor porque o esquema da tabela foi alterado após a declaração do cursor". Às vezes corre bem, outras não. Cada vez que é executado, mesmo que de volta para trás, às vezes funciona e às vezes não. O que poderia causar isso e por que é tão intermitente? O erro pode ser gerado em qualquer chamada para um procedimento em um dos servidores. Nem sempre é o mesmo servidor que ele tenta consultar que produz o erro.
Vale a pena mencionar que tenho vários procedimentos de todos os que fazem algo extremamente semelhante, mas nunca produzem o problema. Mas eles estão todos sob o mesmo esquema (dbo) e esta é a primeira vez que um esquema diferente é usado.
EDIT - esqueci de mencionar que tentei usar um cursor FAST_FORWARD e não parece ajudar.
Tente definir explicitamente seu cursor como
LOCAL STATIC FORWARD_ONLY
.Não sei quais alterações específicas podem estar acontecendo em seus servidores vinculados ou no que esse procedimento armazenado pode estar tocando, mas a estática faz uma cópia dos dados para que o cursor não seja afetado (bem, não se importe) qualquer uma dessas alterações.
Este é o mesmo problema
sp_MSforeachdb
que faz com que ele ignore bancos de dados. Eles usam o tipo errado de cursor e, graças ao tratamento de erros, os bancos de dados que foram tocados de alguma forma desde que o cursor foi aberto são ignorados silenciosamente. É por isso que escrevi um substituto que também está disponível - com algumas melhorias úteis - no First Responder Kit de Brent Ozar Unlimited .Além disso, existe uma maneira melhor de executar SQL dinâmico em bancos de dados/servidores fornecidos por uma variável. Isso geralmente torna possível usar
sp_executesql
e passar parâmetros fortemente tipados (em vez de dobrar aspas em todo lugar, fazer conversões confusas de ints e datas para strings e assim por diante).