Como posso monitorar um banco de dados do SQL Server para alterações em uma tabela sem usar gatilhos ou modificar a estrutura do banco de dados de alguma maneira? Meu ambiente de programação preferido é o .NET e C #.
Eu gostaria de poder oferecer suporte a qualquer SQL Server 2000 SP4 ou mais recente. Meu aplicativo é uma visualização de dados aparafusada para o produto de outra empresa. Nossa base de clientes está na casa dos milhares, por isso não quero exigir que modifiquemos a tabela de fornecedores terceirizados a 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.
Por fim, gostaria que a alteração acionasse um evento no meu aplicativo, em vez de ter que verificar alterações em um intervalo.
O melhor curso de ação, considerando meus requisitos (sem gatilhos ou modificação de esquema, SQL Server 2000 e 2005), parece ser o uso da BINARY_CHECKSUM
função no T-SQL . A maneira que planejo 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 foi alterado, 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.
fonte
Respostas:
Dê uma olhada no comando CHECKSUM:
Isso retornará o mesmo número sempre que for executado, desde que o conteúdo da tabela não tenha sido alterado. Veja meu post sobre isso para obter mais informações:
CHECKSUM
Aqui está como eu o 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)
fonte
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, alterações simétricas resultam no mesmo CHECKSUM!
Por exemplo. a solução
CHECKSUM_AGG(BINARY_CHECKSUM(*))
sempre fornecerá 0 para todas as 3 tabelas com conteúdo diferente:fonte
Por que você não deseja usar gatilhos? Eles são bons se você os usar corretamente. Se você usá-los como uma maneira de impor a integridade referencial, é quando eles vão de bom a ruim. Mas se você usá-los para monitoramento, eles não são realmente considerados tabus.
fonte
Com que frequência você precisa verificar alterações e qual o tamanho (em termos de tamanho da 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. ANOLOCK
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 para cada linha para que você diga que uma foi alterada.Você já pensou em fazer 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 faz o banco de dados?
Eles poderiam implementar uma API que fornece um mecanismo para notificar os aplicativos acessórios que os dados foram alterados. Pode ser tão simples quanto gravar em uma tabela de notificação que lista qual tabela e qual linha foi modificada. Isso pode ser implementado através de gatilhos ou código do aplicativo. Do seu lado, isso não importa, sua única preocupação seria verificar a tabela de notificação periodicamente. O desempenho atingido no banco de dados seria muito menor do que verificar todas as linhas em busca de alterações.
A parte difícil seria convencer o fornecedor do aplicativo a implementar esse recurso. Como isso pode ser tratado inteiramente através do SQL por meio de gatilhos, você pode fazer a maior parte do trabalho para eles escrevendo e testando os gatilhos e levando o código ao fornecedor do aplicativo. Ao fazer com que o fornecedor suporte os acionadores, evita a situação em que a adição de um acionador substitui inadvertidamente um acionador fornecido pelo fornecedor.
fonte
Infelizmente, não acho 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 a
SQLDependency
classe emSystem.Data.SqlClient
. Consulte Notificações de consulta no SQL Server (ADO.NET) .fonte
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 especificada usando as tabelas sistema INFORMAÇÕES_SCHEMA e registra esses dados no repositório de dados. Compare os dados retornados em relação à estrutura da tabela com os dados retornados na hora anterior. Se for diferente, você saberá que a estrutura mudou.
Consulta de exemplo para retornar informações sobre todas as colunas da tabela ABC (idealmente listando apenas as colunas da tabela INFORMATION_SCHEMA que você deseja, em vez de usar * select ** como eu faço aqui):
Você monitoraria diferentes colunas e visualizações de INFORMAÇÕES_SCHEMA, dependendo de como exatamente define "alterações em uma tabela".
fonte
Palpite aqui: Se você não deseja modificar as tabelas de terceiros, é possível criar uma visualização e acionar essa visualização?
fonte
Verifique a data da última confirmação. Todo banco de dados tem um histórico de quando cada confirmação é feita. Eu acredito que é um padrão de conformidade com ACID.
fonte