Pergunta

Como posso monitorar um banco de dados SQL Server em busca de alterações em uma tabela sem usar gatilhos ou modificar a estrutura do banco de dados de alguma forma?Meu ambiente de programação preferido é .LÍQUIDO e C#.

Eu gostaria de poder apoiar qualquer Servidor SQL 2000 SP4 ou mais recente.Meu aplicativo é uma visualização de dados complementar para o produto de outra empresa.Nossa base de clientes está na casa dos milhares, então não quero ter que exigir que modifiquemos a tabela do fornecedor terceirizado em cada instalação.

Por "alterações em uma tabela" Quero dizer alterações nos dados da tabela, não alterações na estrutura da tabela.

Em última análise, gostaria que a alteração acionasse um evento em meu aplicativo, em vez de ter que verificar as alterações em um intervalo.


O melhor curso de ação, dados meus requisitos (sem gatilhos ou modificação de esquema, SQL Server 2000 e 2005) parece ser usar o BINARY_CHECKSUM funcionar em T-SQL.A maneira que pretendo implementar é esta:

A cada X segundos execute a seguinte consulta:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

E compare isso com o valor armazenado.Se o valor mudou, percorra a tabela linha por linha usando a consulta:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

E compare as somas de verificação retornadas com os valores armazenados.

Foi útil?

Solução

Dê uma olhada no comando CHECKSUM:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

Isso retornará o mesmo número cada vez que for executado, desde que o conteúdo da tabela não tenha sido alterado.Veja minha postagem sobre isso para obter mais informações:

SOMA DE VERIFICAÇÃO

Veja como usei para reconstruir dependências de cache quando as tabelas foram alteradas:
Dependência de cache do banco de dados ASP.NET 1.1 (sem gatilhos)

Outras dicas

Infelizmente o CHECKSUM nem sempre funciona corretamente para detectar alterações.

É apenas uma soma de verificação primitiva e nenhum cálculo de verificação de redundância cíclica (CRC).

Portanto, você não pode usá-lo para detectar todas as alterações, por exemplo.g.mudanças simétricas resultam no mesmo CHECKSUM!

E.g.a solução com CHECKSUM_AGG(BINARY_CHECKSUM(*)) sempre entregará 0 para todas as 3 tabelas com conteúdo diferente:


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

Selecione checksum_agg (binary_checksum (*)) de (selecione 1 como numa, 2 como união entorpecido, todos selecionados 1 como numa, 2 como entorpecido) q - entrega 0!

Selecione CheckSum_Agg (binário_checksum (*)) de (selecione 0 como numa, 0 como união entorpecido, todos selecione 0 como numa, 0 como entorpecido) q - entrega 0!

Por que você não quer usar gatilhos?Eles são uma coisa boa se você os usar corretamente.Se você usá-los como uma forma de impor a integridade referencial, é quando eles passam de bons a ruins.Mas se você usá-los para monitoramento, eles não serão considerados tabu.

Com que frequência você precisa verificar alterações e qual o tamanho (em termos de tamanho de linha) das tabelas no banco de dados?Se você usar o CHECKSUM_AGG(BINARY_CHECKSUM(*)) método sugerido por John, ele verificará todas as linhas da tabela especificada.O NOLOCK dica ajuda, mas em um banco de dados grande, você ainda está acessando todas as linhas.Você também precisará armazenar a soma de verificação de cada linha para informar que uma delas foi alterada.

Você já pensou em abordar isso de um ângulo diferente?Se você não deseja modificar o esquema para adicionar gatilhos (o que faz sentido, não é o seu banco de dados), você já pensou em trabalhar com o fornecedor do aplicativo que fabrica o banco de dados?

Eles poderiam implementar uma API que fornecesse um mecanismo para notificar aplicativos acessórios de que os dados foram alterados.Poderia ser tão simples quanto escrever em uma tabela de notificação que lista qual tabela e qual linha foram modificadas.Isso pode ser implementado por meio de gatilhos ou código de aplicativo.Da sua parte, não importaria, sua única preocupação seria verificar a tabela de notificações periodicamente.O impacto no desempenho do banco de dados seria muito menor do que verificar se há alterações em cada linha.

A parte difícil seria convencer o fornecedor do aplicativo a implementar esse recurso.Como isso pode ser tratado inteiramente por meio de SQL por meio de gatilhos, você poderia fazer a maior parte do trabalho escrevendo e testando os gatilhos e, em seguida, levando o código ao fornecedor do aplicativo.Ao fazer com que o fornecedor ofereça suporte aos acionadores, evita-se a situação em que a adição de um acionador substitui inadvertidamente um acionador fornecido pelo fornecedor.

Infelizmente, não creio que exista uma maneira limpa de fazer isso no SQL2000.Se você restringir seus requisitos ao SQL Server 2005 (e posterior), estará no negócio.Você pode usar o SQLDependency aula em System.Data.SqlClient.Ver Notificações de consulta no SQL Server (ADO.NET).

Tenha um trabalho DTS (ou um trabalho iniciado por um serviço do Windows) que seja executado em um determinado intervalo.Cada vez que é executado, ele obtém informações sobre a tabela fornecida usando o sistema INFORMATION_SCHEMA tabelas e registra esses dados no repositório de dados.Compare os dados retornados referentes à estrutura da tabela com os dados retornados da vez anterior.Se for diferente, então você sabe que a estrutura mudou.

Exemplo de consulta para retornar informações sobre todas as colunas da tabela ABC (de preferência listando apenas as colunas da tabela INFORMATION_SCHEMA que você deseja, em vez de usar *select ** como faço aqui):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

Você monitoraria diferentes colunas e visualizações INFORMATION_SCHEMA dependendo de como exatamente você define "alterações em uma tabela".

Adivinhação aqui:Se não quiser modificar as tabelas de terceiros, você pode criar uma visualização e, em seguida, colocar um gatilho nessa visualização?

Verifique a data do último commit.Cada banco de dados possui um histórico de quando cada commit é feito.Acredito que seja um padrão de conformidade com ACID.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top