Kiểm tra các thay đổi đối với bảng SQL Server?


142

Làm cách nào tôi có thể giám sát cơ sở dữ liệu SQL Server để thay đổi bảng mà không cần sử dụng trình kích hoạt hoặc sửa đổi cấu trúc của cơ sở dữ liệu theo bất kỳ cách nào? Môi trường lập trình ưa thích của tôi là .NET và C #.

Tôi muốn có thể hỗ trợ bất kỳ SQL Server 2000 nào SP4 hoặc mới hơn. Ứng dụng của tôi là một trực quan hóa dữ liệu cho sản phẩm của công ty khác. Cơ sở khách hàng của chúng tôi có hàng ngàn người, vì vậy tôi không muốn phải đưa ra các yêu cầu rằng chúng tôi sửa đổi bảng của nhà cung cấp bên thứ ba trong mỗi lần cài đặt.

Bằng cách "thay đổi bảng" Tôi có nghĩa là thay đổi dữ liệu bảng, không thay đổi cấu trúc bảng.

Cuối cùng, tôi muốn thay đổi để kích hoạt một sự kiện trong ứng dụng của mình, thay vì phải kiểm tra các thay đổi trong một khoảng thời gian.


Cách hành động tốt nhất theo yêu cầu của tôi (không kích hoạt hoặc sửa đổi lược đồ, SQL Server 2000 và 2005) dường như là sử dụng BINARY_CHECKSUMhàm trong T-SQL . Cách tôi dự định thực hiện là thế này:

Cứ sau X giây lại chạy truy vấn sau:

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

Và so sánh với giá trị được lưu trữ. Nếu giá trị đã thay đổi, hãy đi qua từng hàng trong bảng bằng cách sử dụng truy vấn:

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

Và so sánh tổng kiểm tra trả lại với các giá trị được lưu trữ.


3
Họ đã không đặt dấu thời gian sửa đổi lần cuối trên hàng của họ, phải không?
zmbq

Đối với bản ghi, nếu hỗ trợ phiên bản là SQL Server 2005 hoặc mới hơn. Tôi sẽ xem xét tính năng Nhà môi giới dịch vụ của SQL Server.
Marco Guignard

Câu trả lời:


97

Hãy xem lệnh CHECKSUM:

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

Điều đó sẽ trả về cùng một số mỗi lần nó chạy miễn là nội dung bảng không thay đổi. Xem bài viết của tôi về điều này để biết thêm thông tin:

KIỂM TRA

Đây là cách tôi sử dụng nó để xây dựng lại các phụ thuộc bộ đệm khi các bảng thay đổi:
phụ thuộc bộ đệm cơ sở dữ liệu ASP.NET 1.1 (không có trình kích hoạt)


2
Tổng kiểm tra có thể và sẽ thất bại cuối cùng. Nếu hệ thống của bạn chấp nhận rằng hai bộ dữ liệu khác nhau sẽ dẫn đến cùng một tổng kiểm tra, thì bạn vẫn ổn. Vì lý do đó, tôi đã phải rời khỏi tổng kiểm tra trong hầu hết các hệ thống của chúng tôi ...
LPains

@LPains bạn có thể vui lòng giải thích về tuyên bố của bạn?
petrosmm

1
@petrosmm Tôi không chắc bạn muốn tôi giải thích cụ thể điều gì, nhưng tôi sẽ thử. Hãy tưởng tượng bạn có một bảng với vài trăm bản ghi, về cơ bản bạn tạo một số nguyên dưới dạng tổng kiểm tra, mức độ thường xuyên sẽ va chạm? Trong trường hợp của tôi, tôi đã làm điều đó với khoảng 10 bảng, tất cả có hàng trăm hồ sơ. Tôi đã có ít nhất một vụ va chạm mỗi ngày. Kiểm tra câu trả lời khác stackoverflow.com/questions/14450415/ trên
LPains

29

Thật không may, CHECKSUM không phải lúc nào cũng hoạt động đúng để phát hiện các thay đổi .

Nó chỉ là một tổng kiểm tra nguyên thủy và không tính toán kiểm tra dự phòng chu kỳ (CRC).

Do đó, bạn không thể sử dụng nó để phát hiện tất cả các thay đổi, ví dụ: các thay đổi đối xứng dẫn đến cùng một KIỂM TRA!

Ví dụ. giải pháp với CHECKSUM_AGG(BINARY_CHECKSUM(*))sẽ luôn cung cấp 0 cho cả 3 bảng với nội dung khác nhau:


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
Đó thực sự không phải là một câu trả lời, đó là "đề xuất của bạn không hoạt động".
kristianp

1
Điều này có thể được khắc phục cho dữ liệu trùng lặp bằng cách sử dụng từ khóa DISINCT trước BINary_CHECKSUM. Có một vài cạm bẫy khác được thảo luận ở đây nhưng không chính xác là các tình huống phổ biến.
pblack

25

Tại sao bạn không muốn sử dụng kích hoạt? Chúng là một điều tốt nếu bạn sử dụng chúng một cách chính xác. Nếu bạn sử dụng chúng như một cách để thực thi tính toàn vẹn tham chiếu đó là khi chúng đi từ tốt đến xấu. Nhưng nếu bạn sử dụng chúng để theo dõi, chúng không thực sự được coi là điều cấm kỵ.


20

Tần suất bạn cần kiểm tra các thay đổi và mức độ lớn (về kích thước hàng) của các bảng trong cơ sở dữ liệu? Nếu bạn sử dụng CHECKSUM_AGG(BINARY_CHECKSUM(*))phương thức được đề xuất bởi John, nó sẽ quét mọi hàng của bảng được chỉ định. CácNOLOCK gợi ý giúp, nhưng trên một cơ sở dữ liệu lớn, bạn vẫn đánh mỗi hàng. Bạn cũng sẽ cần lưu trữ tổng kiểm tra cho mỗi hàng để bạn nói một hàng đã thay đổi.

Bạn đã xem xét việc này ở một góc độ khác? Nếu bạn không muốn sửa đổi lược đồ để thêm các kích hoạt, (điều này có ý nghĩa, đó không phải là cơ sở dữ liệu của bạn), bạn đã xem xét làm việc với nhà cung cấp ứng dụng tạo cơ sở dữ liệu chưa?

Họ có thể triển khai API cung cấp cơ chế thông báo cho các ứng dụng phụ kiện mà dữ liệu đã thay đổi. Nó có thể đơn giản như viết vào bảng thông báo liệt kê bảng nào và hàng nào đã được sửa đổi. Điều đó có thể được thực hiện thông qua kích hoạt hoặc mã ứng dụng. Về phía bạn, ti sẽ không thành vấn đề, mối quan tâm duy nhất của bạn sẽ là quét bảng thông báo theo định kỳ. Hiệu suất đạt được trên cơ sở dữ liệu sẽ ít hơn nhiều so với việc quét mọi hàng để thay đổi.

Phần khó sẽ thuyết phục được nhà cung cấp ứng dụng thực hiện tính năng này. Vì điều này có thể được xử lý hoàn toàn thông qua SQL thông qua các trình kích hoạt, bạn có thể thực hiện phần lớn công việc cho chúng bằng cách viết và kiểm tra các trình kích hoạt và sau đó đưa mã đến nhà cung cấp ứng dụng. Bằng cách có nhà cung cấp hỗ trợ các trình kích hoạt, nó sẽ ngăn chặn tình huống bạn thêm trình kích hoạt vô tình thay thế trình kích hoạt do nhà cung cấp cung cấp.


18

Thật không may, tôi không nghĩ rằng có một cách rõ ràng để làm điều này trong SQL2000. Nếu bạn thu hẹp yêu cầu của mình vào SQL Server 2005 (và sau này), thì bạn đang kinh doanh. Bạn có thể sử dụng các SQLDependencylớp trong System.Data.SqlClient. Xem Thông báo truy vấn trong SQL Server (ADO.NET) .


16

Có một công việc DTS (hoặc một công việc được bắt đầu bởi một dịch vụ windows) chạy trong một khoảng thời gian nhất định. Mỗi lần chạy, nó sẽ nhận được thông tin về bảng đã cho bằng cách sử dụng các bảng Information_SCHema của hệ thống và ghi lại dữ liệu này vào kho lưu trữ dữ liệu. So sánh dữ liệu được trả về liên quan đến cấu trúc của bảng với dữ liệu được trả về lần trước. Nếu nó khác, thì bạn biết rằng cấu trúc đã thay đổi.

Ví dụ truy vấn để trả về thông tin liên quan đến tất cả các cột trong bảng ABC (lý tưởng nhất là chỉ liệt kê các cột từ bảng Information_SCHema mà bạn muốn, thay vì sử dụng * select ** như tôi làm ở đây):

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

Bạn sẽ theo dõi các cột khác nhau và các khung nhìn Information_SCHema tùy thuộc vào cách bạn xác định chính xác "thay đổi thành bảng".


2
Câu hỏi là về những thay đổi trong dữ liệu bảng và information_schema chứa lược đồ (định nghĩa cột) của bảng.
quá

13

Dự đoán hoang dã ở đây: Nếu bạn không muốn sửa đổi các bảng của bên thứ ba, Bạn có thể tạo chế độ xem và sau đó đặt trình kích hoạt cho chế độ xem đó không?


6

Kiểm tra ngày cam kết cuối cùng. Mỗi cơ sở dữ liệu có một lịch sử khi mỗi cam kết được thực hiện. Tôi tin rằng đó là một tiêu chuẩn tuân thủ ACID.


1
Vui lòng cung cấp một cách tài liệu để nhận thông tin này trong phạm vi bảng trong SQL Server
Martin Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.