Verificar alterações em uma tabela do SQL Server?


142

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_CHECKSUMfunçã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.


3
Eles não colocaram um carimbo de data e hora da última modificação em suas linhas, colocaram?
Zmbq

Para o registro, se o suporte à versão for SQL Server 2005 ou mais recente. Vou dar uma olhada no recurso Service Broker do SQL Server.
Marco Guignard

Respostas:


97

Dê uma olhada no comando CHECKSUM:

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

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)


2
As somas de verificação podem e falharão eventualmente. Se o seu sistema aceitar que dois conjuntos diferentes de dados resultarão na mesma soma de verificação, você estará bem. Por essa razão, eu tive que afastar-se de somas de verificação na maioria dos nossos sistemas ...
LPains

@LPains, você pode elaborar sua declaração?
25418 petrosmm

1
@petrosmm Não sei o que especificamente você quer que eu elabore, mas vou tentar. Imagine que você tem uma tabela com algumas centenas de registros, você basicamente gera um número inteiro como uma soma de verificação, com que frequência isso colidirá? No meu caso, eu fazia isso com cerca de 10 tabelas, todas com centenas de registros. Eu tive pelo menos uma colisão por dia. Verifique esta outra resposta stackoverflow.com/questions/14450415/…
LPains

29

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:


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!

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

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


5
Isso não é realmente uma resposta, é uma "sua sugestão não funciona".
precisa saber é

1
Isso pode ser remediado para dados duplicados usando a palavra-chave DISINCT antes do BINARY_CHECKSUM. Existem algumas outras armadilhas discutidas aqui, mas não cenários exatamente comuns.
pblack

25

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.


20

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. A NOLOCKdica 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.



16

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):

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

Você monitoraria diferentes colunas e visualizações de INFORMAÇÕES_SCHEMA, dependendo de como exatamente define "alterações em uma tabela".


2
A pergunta é sobre alterações nos dados da tabela e information_schema contém o esquema (definições de coluna) da tabela.
também

13

Palpite aqui: Se você não deseja modificar as tabelas de terceiros, é possível criar uma visualização e acionar essa visualização?


6

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.


1
Por favor, forneça uma forma documentada de obter esta informação escopo para uma tabela no SQL Server
Martin Smith
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.