Перевірте зміни в таблиці SQL Server?


142

Як я можу відстежувати базу даних SQL Server щодо змін у таблиці, не використовуючи тригери чи будь-яким чином змінюючи структуру бази даних? Моє бажане середовище програмування .NET і C #.

Я хотів би мати можливість підтримувати будь-який SQL Server 2000 SP4 або новіший. Моя програма - це візуалізація даних, що підлягає детальній розробці, для іншого товару. Наша клієнтська база налічує тисячі, тому я не хочу вимагати вимог щодо того, щоб ми змінювали таблицю сторонніх постачальників при кожній установці.

Під "змінами в таблиці" я маю на увазі зміни в даних таблиці, а не зміни в структурі таблиці.

Зрештою, я хотів би, щоб зміни викликали подію в моїй програмі, замість того, щоб періодично перевіряти зміни.


Найкращий спосіб дії з огляду на мої вимоги (відсутність тригерів чи модифікація схеми, SQL Server 2000 та 2005), здається, використовує BINARY_CHECKSUMфункцію в T-SQL . Я планую реалізувати такий:

Кожні X секунд виконуйте такий запит:

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

І порівняйте це із збереженим значенням. Якщо значення змінилося, перейдіть через таблицю за рядком за допомогою запиту:

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

І порівняйте повернені контрольні суми із збереженими значеннями.


3
Їм не траплялося ставити останню змінену мітку часу на свої ряди, чи не так?
zmbq

Для запису, якщо підтримка версії є SQL Server 2005 або новішої версії. Я ознайомлюсь із функцією Service Broker SQL Server.
Марко

Відповіді:


97

Погляньте на команду CHECKSUM:

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

Це буде повертати те саме число кожного разу, коли його запустити, доки вміст таблиці не змінився. Дивіться мою публікацію з цього приводу для отримання додаткової інформації:

ЧЕКСУМ

Ось як я використовував його для відновлення кеш-залежностей при зміні таблиць:
залежність кешу бази даних ASP.NET 1.1 (без тригерів)


2
Контрольні суми можуть і не вдаються в підсумку. Якщо ваша система визнає, що два різних набори даних призведе до тієї ж контрольної суми, то ви добре. З цієї причини мені довелося відійти від контрольних сум у більшості наших систем ...
LPains

@LPains, чи можете ви детальніше розглянути свою заяву?
petrosmm

1
@petrosmm Я не впевнений, що конкретно ви хочете розробити, але спробую. Уявіть, у вас є таблиця з кількома сотнями записів, ви по суті генеруєте ціле число в якості контрольної суми, як часто це стикається? У моєму випадку я робив це з приблизно 10 таблицями, усі з сотнями записів. У мене було щонайменше одне зіткнення в день. Перевірте інший відповідь stackoverflow.com/questions/14450415 / ...
LPains

29

На жаль, CHECKSUM не завжди працює належним чином для виявлення змін .

Це лише примітивна контрольна сума і не обчислення циклічної надмірності (CRC).

Тому ви не можете використовувати його для виявлення всіх змін, наприклад, симетричні зміни призводять до того ж КОНТРОЛУ!

E. g. рішення з CHECKSUM_AGG(BINARY_CHECKSUM(*))завжди буде доставляти 0 для всіх 3 таблиць з різним вмістом:


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
Це насправді не відповідь, це "ваша пропозиція не працює".
Крістіанп

1
Це можна усунути для дублюваних даних за допомогою ключового слова DISINCT перед BINARY_CHECKSUM. Є обговорили кілька інших підводних каменів тут , але не зовсім загальні сценарії.
pblack

25

Чому ви не хочете використовувати тригери? Вони гарні речі, якщо ви правильно їх використовуєте. Якщо ви використовуєте їх як спосіб закріпити референтну цілісність, коли вони переходять від добра до поганої. Але якщо ви використовуєте їх для моніторингу, вони насправді не вважаються табу.


20

Як часто потрібно перевіряти зміни та наскільки великими (з точки зору розміру рядків) є таблиці в базі даних? Якщо ви використовуєте CHECKSUM_AGG(BINARY_CHECKSUM(*))метод, запропонований Іваном, він перевірятиме кожен рядок вказаної таблиці. TheNOLOCKПідказка допомагає, але на великій базі даних, ви все ще ударяти кожен рядок. Вам також потрібно буде зберігати контрольну суму для кожного ряду, щоб ви сказали, що одна змінилася.

Ви думали про те, щоб піти з цим під іншим кутом? Якщо ви не хочете змінювати схему, щоб додати тригери (це має сенс, це не ваша база даних), чи планували ви працювати з постачальником додатка, який робить базу даних?

Вони могли б реалізувати API, який забезпечує механізм оповіщення додатків додатків про зміни даних. Це може бути так само просто, як записувати до таблиці сповіщень, у якій перераховано, яку таблицю та який рядок було змінено. Це може бути реалізовано через тригери або код програми. З вашого боку, ти не мав би значення, вашим єдиним клопотом буде періодичне сканування таблиці сповіщень. Показ ефективності в базі даних був би набагато меншим, ніж сканування змін у кожній рядці.

Важкою частиною було б переконати постачальника додатків реалізувати цю функцію. Оскільки це можна вирішувати повністю через SQL через тригери, ви можете виконати основну роботу над ними, написавши та протестуючи тригери, а потім донести код до постачальника програми. Завдяки тому, що постачальник підтримує тригери, це запобігає ситуації, коли додавання тригера ненавмисно замінює тригер, наданий постачальником.


18

На жаль, я не думаю, що існує чистий спосіб зробити це в SQL2000. Якщо ви звужуєте свої вимоги до SQL Server 2005 (і пізніших версій), ви займаєтеся бізнесом. Ви можете використовувати SQLDependencyклас у System.Data.SqlClient. Див. Сповіщення про запити в SQL Server (ADO.NET) .


16

Майте роботу DTS (або роботу, яку розпочинає служба Windows), яка працює з заданим інтервалом. Кожен раз, коли він запускається, він отримує інформацію про дану таблицю за допомогою системних таблиць INFORMATION_SCHEMA та записує ці дані у сховище даних. Порівняйте дані, повернуті щодо структури таблиці, з даними, поверненими попереднього разу. Якщо це інакше, то ви знаєте, що структура змінилася.

Приклад запиту для повернення інформації стосовно всіх стовпців таблиці ABC (в ідеалі перелічіть лише стовпці з таблиці INFORMATION_SCHEMA, яку ви хочете, замість того, щоб використовувати * select **, як я тут):

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

Ви б відстежували різні стовпці та перегляди INFORMATION_SCHEMA залежно від того, як саме ви визначаєте "зміни таблиці".


2
Питання стосується змін у даних таблиці, а інформація_схеми містить схему (визначення стовпців) таблиці.
теж

13

Дикі здогадки тут: Якщо ви не хочете змінювати таблиці третіх сторін, чи можете ви створити подання, а потім поставити на нього подання?


6

Перевірте останню дату фіксації. У кожній базі даних є історія, коли виконується кожен фіксатор. Я вважаю, що це стандарт відповідності ACID.


1
Будь ласка, надайте задокументований спосіб отримати цю інформацію до таблиці в SQL Server
Мартін Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.