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




sql server search column in tables (6)

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 é .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 terceiros em todas as instalações.

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 precisar verificar as 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 função BINARY_CHECKSUM 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.


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 método CHECKSUM_AGG(BINARY_CHECKSUM(*)) sugerido por John, ele verificará todas as linhas da tabela especificada. A dica NOLOCK 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 acionadores (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ções 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 manipulado inteiramente por meio do SQL por meio de gatilhos, você pode fazer a maior parte do trabalho escrevendo e testando os gatilhos e levando o código ao fornecedor do aplicativo. Ao fazer com que o fornecedor ofereça suporte aos gatilhos, evita a situação em que a adição de um gatilho substitui inadvertidamente um gatilho fornecido pelo fornecedor.


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)


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


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 passam de bom para ruim. Mas se você usá-los para monitoramento, eles não são realmente considerados tabus.


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.


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 com 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!





rdbms