Вопрос

Как я могу отслеживать базу данных SQL Server на предмет изменений в таблице без использования триггеров или каким-либо образом изменяя структуру базы данных?Моя предпочтительная среда программирования — .СЕТЬ и С#.

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

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

В конечном счете, я бы хотел, чтобы изменение вызывало событие в моем приложении, вместо того, чтобы проверять наличие изменений через определенные промежутки времени.


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

Каждые X секунд выполняется следующий запрос:

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

И сравните это с сохраненным значением.Если значение изменилось, пройдитесь по таблице построчно с помощью запроса:

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

И сравните возвращенные контрольные суммы с сохраненными значениями.

Это было полезно?

Решение

Взгляните на команду CHECKSUM:

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

Это будет возвращать одно и то же число каждый раз при запуске, если содержимое таблицы не изменилось.Дополнительную информацию смотрите в моем посте по этому поводу:

КОНТРОЛЬНАЯ СУММА

Вот как я использовал его для восстановления зависимостей кеша при изменении таблиц:
Зависимость кэша базы данных ASP.NET 1.1 (без триггеров)

Другие советы

К сожалению, CHECKSUM не всегда работает должным образом для обнаружения изменений..

Это всего лишь примитивная контрольная сумма, а не расчет циклического избыточного кода (CRC).

Поэтому вы не можете использовать его для обнаружения всех изменений, например.г.симметричные изменения приводят к одной и той же КОНТРОЛЬНОЙ СУММЕ!

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


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!

Выберите CheckSum_agg (binary_checksum (*)) из (выберите 1 как NUMA, 2 как онемение, все выберите 1 как NUMA, 2 как онемение) Q - Получите 0!

Выберите CheckSum_agg (binary_checksum (*)) из (выберите 0 как Numa, 0 как онментный союз, все выберите 0 как Numa, 0 как онемение) Q - Получите 0!

Почему вы не хотите использовать триггеры?Это хорошая вещь, если вы используете их правильно.Если вы используете их как способ обеспечить ссылочную целостность, тогда они переходят от хорошего к плохому.Но если вы используете их для мониторинга, на самом деле они не считаются табу.

Как часто вам нужно проверять изменения и насколько велики (по размеру строк) таблицы в базе данных?Если вы используете CHECKSUM_AGG(BINARY_CHECKSUM(*)) метод, предложенный Джоном, он сканирует каждую строку указанной таблицы.А NOLOCK подсказка помогает, но в большой базе данных вы все равно попадаете в каждую строку.Вам также необходимо будет сохранить контрольную сумму для каждой строки, чтобы вы могли сообщить, что она изменилась.

Вы рассматривали возможность подойти к этому вопросу под другим углом?Если вы не хотите изменять схему для добавления триггеров (что имеет смысл, ведь это не ваша база данных), рассматривали ли вы возможность сотрудничества с поставщиком приложения, который создает базу данных?

Они могли бы реализовать API, который обеспечивает механизм уведомления дополнительных приложений об изменении данных.Это может быть так же просто, как запись в таблицу уведомлений, в которой указано, какая таблица и какая строка были изменены.Это можно реализовать с помощью триггеров или кода приложения.С вашей стороны это не имеет значения, вашей единственной заботой будет периодическое сканирование таблицы уведомлений.Снижение производительности базы данных будет гораздо меньшим, чем при сканировании каждой строки на наличие изменений.

Сложнее всего будет убедить поставщика приложения реализовать эту функцию.Поскольку это можно сделать полностью через SQL с помощью триггеров, вы можете выполнить за них большую часть работы, написав и протестировав триггеры, а затем передав код поставщику приложения.Поддержка триггеров поставщиком предотвращает ситуацию, когда добавленный вами триггер случайно заменяет триггер, предоставленный поставщиком.

К сожалению, я не думаю, что в SQL2000 существует простой способ сделать это.Если вы сузите свои требования до SQL Server 2005 (и более поздних версий), то вы в деле.Вы можете использовать SQLDependency класс в System.Data.SqlClient.Видеть Уведомления о запросах в SQL Server (ADO.NET).

Иметь задание DTS (или задание, запускаемое службой Windows), которое выполняется с заданным интервалом.При каждом запуске он получает информацию о данной таблице, используя систему ИНФОРМАЦИЯ_СХЕМА таблицы и записывает эти данные в хранилище данных.Сравните возвращенные данные относительно структуры таблицы с данными, возвращенными в предыдущий раз.Если оно другое, то знайте, что структура изменилась.

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

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

Вы будете отслеживать различные столбцы и представления INFORMATION_SCHEMA в зависимости от того, как именно вы определяете «изменения в таблице».

Дикая догадка здесь:Если вы не хотите изменять сторонние таблицы, можете ли вы создать представление, а затем назначить триггер для этого представления?

Проверьте дату последней фиксации.Каждая база данных имеет историю того, когда был сделан каждый коммит.Я считаю, что это стандарт соответствия ACID.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top