Vă mulțumim pentru susținere

Verificați pentru modificări într-o tabelă SQL Server?

Cum pot monitoriza o bază de date SQL Server pentru modificări într-o tabelă fără a utiliza declanșatoarele sau modificarea structurii bazei de date în vreun fel? Mediul meu de programare preferat este .NET și C #.

Aș dori să fiu în stare să accept orice SQL Server 2000 SP4 sau mai nou. Aplicația mea este o vizualizare a datelor pentru un produs al unei alte companii. Baza noastră de clienți este în mii, deci nu vreau să trebuiască să introduc cerințe pe care le modificăm masa furnizorilor de la terți la fiecare instalare.

Prin "modificări într-o tabelă" Adică modificări ale datelor din tabel, nu modificări ale structurii tabelului.

În cele din urmă, aș dori ca schimbarea să declanșeze un eveniment în cererea mea, în loc să trebuiască să verifici schimbările la un interval.


Cel mai bun mod de acțiune, dat fiind cerințele mele (fără declanșatori sau modificări ale schemelor, SQL Server 2000 și 2005) pare să fie utilizarea funcției BINARY_CHECKSUM în T-SQL . Modul pe care intenționez să îl pun în aplicare este acesta:

La fiecare X secunde executați următoarea interogare:

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

Comparați-le cu valoarea stocată. Dacă valoarea s-a modificat, treceți prin rândul de rând pe rând folosind interogarea:

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

Comparați sumele de control returnate cu valorile stocate.

0
adăugat editat
Nu s-au întâmplat să pună un timbru de ultimă oră modificat pe rândurile lor, nu-i așa?
adăugat autor zmbq

8 răspunsuri

De ce nu doriți să utilizați declanșatoarele? Ele sunt un lucru bun dacă le folosiți corect. Dacă le folosiți ca o modalitate de a impune integritate referențială, atunci când acestea merg de la bun la rău. Dar dacă le folosiți pentru monitorizare, acestea nu sunt considerate tabu.

0
adăugat

Ghiciți-vă bine aici: dacă nu doriți să modificați tabelele terților, puteți să creați o vizualizare și apoi să puneți un declanșator în acea vizualizare?

0
adăugat

Aveți o activitate DTS (sau o activitate inițiată de un serviciu Windows) care rulează la un interval dat. De fiecare dată când se execută, primește informații despre tabelul dat utilizând sistemul INFORMATION_SCHEMA și înregistrează aceste date în depozitul de date. Comparați datele returnate cu privire la structura tabelului cu datele returnate la ora precedentă. Dacă este diferită, atunci știi că structura sa schimbat.

Exemplu de interogare pentru a returna informații despre toate coloanele din tabelul ABC (în mod ideal, afișați doar coloanele din tabelul INFORMATION_SCHEMA pe care doriți, în loc să utilizați * selectați ** așa cum fac aici):

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

Veți monitoriza diferitele coloane și opțiunile INFORMAȚII_SCHEMA în funcție de modul în care definiți "modificările aduse unui tabel".

0
adăugat
Întrebarea se referă la modificările din datele tabelului și informația_schema conține schema (definițiile coloanelor) din tabel.
adăugat autor too

Cât de des trebuie să verificați modificările și cât de mari (în ceea ce privește dimensiunea rândului) sunt tabelele din baza de date? Dacă utilizați metoda CHECKSUM_AGG (BINARY_CHECKSUM (*)) sugerată de John, aceasta va scana fiecare rând din tabelul specificat. Indicația NOLOCK ajută, dar pe o bază de date mare, încă mai apăsați fiecare rând. De asemenea, va trebui să stocați suma de control pentru fiecare rând, astfel încât să-i spuneți că cineva sa schimbat.

Te-ai gândit la asta dintr-un alt unghi? Dacă nu doriți să modificați schema pentru a adăuga declanșatori (ceea ce face sens, nu este baza dvs. de date), ați gândit să lucrați cu furnizorul de aplicații care face baza de date?

Aceștia ar putea implementa un API care să ofere un mecanism de notificare a aplicațiilor accesoriu că datele s-au schimbat. Ar putea fi la fel de simplu ca scrierea unui tabel de notificare care să indice ce tabelă și ce rând au fost modificate. Acest lucru ar putea fi implementat prin triggere sau cod de aplicație. Din partea dvs., nu va conteaza, singura dvs. preocupare ar fi scanarea tabelului de notificare periodic. Performanța lovită în baza de date ar fi mult mai puțin decât scanarea fiecărui rând pentru modificări.

Partea greu ar fi convingerea furnizorului de aplicații să implementeze această caracteristică. Deoarece acest lucru se poate face în întregime prin SQL prin declanșatoare, ați putea face cea mai mare parte a lucrării pentru ei scriind și testarea declanșatoarelor și apoi aducerea codului la furnizorul de aplicații. Având suportul vânzătorului declanșatorii, acesta împiedică situația în care adăugarea unui declanșator înlocuiește din neatenție un declanșator furnizat de furnizor.

0
adăugat

Uitați-vă la comanda CHECKSUM:

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

Aceasta va returna același număr de fiecare dată când este rulat, atâta timp cât conținutul tabelului nu sa schimbat. Vedeți postarea mea despre asta pentru mai multe informații:

CHECKSUM

Here's how I used it to rebuild cache dependencies when tables changed:
ASP.NET 1.1 database cache dependency (without triggers)

0
adăugat
Sumele de verificare pot și nu vor reuși în cele din urmă. Dacă sistemul dvs. acceptă faptul că două seturi diferite de date vor avea ca rezultat aceeași sumă de verificare, decât vă simțiți bine. Din acest motiv, a trebuit să mă îndepărtez de sumele de control în majoritatea sistemelor noastre ...
adăugat autor LPains

Din păcate, nu cred că există un mod curat de a face acest lucru în SQL2000. Dacă vă restrângeți cerințele la SQL Server 2005 (și mai târziu), atunci sunteți în afaceri. Puteți utiliza clasa SQLDependency în System.Data.SqlClient . Vedeți Notificările de interogare în SQL Server (ADO.NET) .

0
adăugat

Verificați ultima dată de comitere. Fiecare bază de date are un istoric în care se efectuează fiecare comitet. Eu cred că este un standard de conformitate cu ACID.

0
adăugat

Unfortunately CHECKSUM does not work always properly to detect changes. It is only a primitive checksum and no CRC calculation. Therefore you can't use it to detect all changes, e. g. symmetrical changes result in the same CHECKSUM!

De exemplu. soluția cu CHECKSUM_AGG (BINARY_CHECKSUM (*)) oferă întotdeauna 0 pentru toate cele 3 tabele cu conținut diferit!


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!
0
adăugat
Acesta nu este de fapt un răspuns, este o "sugestia dvs. nu funcționează".
adăugat autor kristianp
Acest lucru poate fi remediat pentru datele duplicate utilizând cuvântul cheie DISINCT înainte de BINARY_CHECKSUM. Există câteva alte capcane discutate aici , dar nu chiar foarte frecvente scenarii.
adăugat autor pblack