Programming

SQL Server 테이블의 변경 사항을 확인 하시겠습니까?

procodes 2020. 6. 23. 08:05
반응형

SQL Server 테이블의 변경 사항을 확인 하시겠습니까?


트리거를 사용하거나 데이터베이스 구조를 수정하지 않고 테이블 변경 사항을 SQL Server 데이터베이스에서 어떻게 모니터링 할 수 있습니까? 내가 선호하는 프로그래밍 환경은 .NET 및 C #입니다.

모든 SQL Server 2000 SP4 이상 을 지원하고 싶습니다 . 내 응용 프로그램은 다른 회사 제품의 볼트 온 데이터 시각화입니다. 고객 기반은 수천 명이므로 모든 설치시 타사 공급 업체의 테이블을 수정해야하는 요구 사항을 적용하고 싶지 않습니다.

에 의해 "테이블로 변경" , 테이블 데이터에 대한 I 평균 변경 테이블 구조를 변경하지.

궁극적으로 변경 사항을 주기적으로 확인하지 않고 응용 프로그램에서 이벤트를 트리거하기 위해 변경 사항을 원합니다.


내 요구 사항 (트리거 또는 스키마 수정 없음, SQL Server 2000 및 2005)을 고려한 가장 좋은 방법 BINARY_CHECKSUMT-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 (Cyclic Redundancy Check) 계산은 없습니다.

따라서 모든 변경 사항을 감지하는 데 사용할 수 없습니다. 예를 들어 대칭 변경으로 인해 동일한 CHECKSUM이 발생합니다!

예 : 솔루션 CHECKSUM_AGG(BINARY_CHECKSUM(*))은 내용이 다른 3 개의 테이블 모두에 대해 항상 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!

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!


왜 트리거를 사용하고 싶지 않습니까? 올바르게 사용하면 좋은 것입니다. 참조 무결성을 강화하기위한 방법으로 사용하는 경우, 그들이 좋은 것에서 나쁜 것으로 갈 때입니다. 그러나 모니터링에 사용하면 실제로 금기 사항으로 간주되지 않습니다.


How often do you need to check for changes and how large (in terms of row size) are the tables in the database? If you use the CHECKSUM_AGG(BINARY_CHECKSUM(*)) method suggested by John, it will scan every row of the specified table. The NOLOCK hint helps, but on a large database, you are still hitting every row. You will also need to store the checksum for every row so that you tell one has changed.

Have you considered going at this from a different angle? If you do not want to modify the schema to add triggers, (which makes a sense, it's not your database), have you considered working with the application vendor that does make the database?

They could implement an API that provides a mechanism for notifying accessory apps that data has changed. It could be as simple as writing to a notification table that lists what table and which row were modified. That could be implemented through triggers or application code. From your side, ti wouldn't matter, your only concern would be scanning the notification table on a periodic basis. The performance hit on the database would be far less than scanning every row for changes.

The hard part would be convincing the application vendor to implement this feature. Since this can be handles entirely through SQL via triggers, you could do the bulk of the work for them by writing and testing the triggers and then bringing the code to the application vendor. By having the vendor support the triggers, it prevent the situation where your adding a trigger inadvertently replaces a trigger supplied by the vendor.


Unfortunately, I do not think that there is a clean way to do this in SQL2000. If you narrow your requirements to SQL Server 2005 (and later), then you are in business. You can use the SQLDependency class in System.Data.SqlClient. See Query Notifications in SQL Server (ADO.NET).


Have a DTS job (or a job that is started by a windows service) that runs at a given interval. Each time it is run, it gets information about the given table by using the system INFORMATION_SCHEMA tables, and records this data in the data repository. Compare the data returned regarding the structure of the table with the data returned the previous time. If it is different, then you know that the structure has changed.

Example query to return information regarding all of the columns in table ABC (ideally listing out just the columns from the INFORMATION_SCHEMA table that you want, instead of using *select ** like I do here):

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

You would monitor different columns and INFORMATION_SCHEMA views depending on how exactly you define "changes to a table".


Wild guess here: If you don't want to modify the third party's tables, Can you create a view and then put a trigger on that view?


Check the last commit date. Every database has a history of when each commit is made. I believe its a standard of ACID compliance.

참고URL : https://stackoverflow.com/questions/36/check-for-changes-to-an-sql-server-table

반응형