如何在不使用触发器或以任何方式修改数据库结构的情况下监视SQL Server数据库以查找表的更改?我首选的编程环境是.NET和C#。
我希望能够支持任何SQL Server 2000 SP4或更新版本。我的应用程序是另一家公司产品的螺栓式数据可视化。我们的客户群数以千计,因此我不想在每次安装时都要求我们修改第三方供应商的表格。
通过“更改为表格”我的意思是更改表数据,而不是更改表结构。
最终,我希望更改能够在我的应用程序中触发事件,而不必每隔一段时间检查一次更改。
根据我的要求(没有触发器或架构修改,SQL Server 2000和2005),最好的行动方案似乎是使用T-SQL中的BINARY_CHECKSUM
函数。我计划实施的方式是:
每隔X秒运行以下查询:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);
并将其与存储值进行比较。如果值已更改,请使用查询逐行查看表:
SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);
将返回的校验和与存储的值进行比较。
答案 0 :(得分:93)
看看CHECKSUM命令:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);
只要表格内容没有改变,每次运行时都会返回相同的数字。有关详细信息,请参阅我的帖子:
以下是我在表格更改时使用它来重建缓存依赖关系的方法:
ASP.NET 1.1 database cache dependency (without triggers)
答案 1 :(得分:30)
不幸的是,CHECKSUM并不总能正常检测到变化。
它只是一个原始校验和,没有循环冗余校验(CRC)计算。
因此,您无法使用它来检测所有更改,例如: G。对称的变化会产生相同的CHECKSUM!
电子。 G。具有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!
答案 2 :(得分:25)
为什么不想使用触发器?如果你正确使用它们,它们是一件好事。如果您将它们用作强制参照完整性的一种方式,那就是它们从好的变为坏的时候。但是如果你使用它们进行监控,它们实际上并不被认为是禁忌。
答案 3 :(得分:20)
您需要多久检查一次更改以及数据库中表格的大小(以行大小计)?如果使用John建议的CHECKSUM_AGG(BINARY_CHECKSUM(*))
方法,它将扫描指定表的每一行。 NOLOCK
提示有帮助,但在大型数据库中,您仍然会遇到每一行。您还需要为每一行存储校验和,以便告知其中一行已更改。
您是否考虑过从不同角度进行此操作?如果您不想修改架构以添加触发器(从某种意义上说,它不是您的数据库),您是否考虑过与构建数据库的应用程序供应商合作?
他们可以实现一个API,该API提供一种机制,用于通知附件应用程序数据已更改。它可以像写入通知表一样简单,该通知表列出了哪些表和哪些行被修改。这可以通过触发器或应用程序代码实现。在您身边,ti无关紧要,您唯一关心的是定期扫描通知表。数据库中的性能损失远远小于扫描每一行的更改。
困难的部分是说服应用程序供应商实现此功能。由于这可以通过SQL通过触发器完全处理,因此您可以通过编写和测试触发器然后将代码提供给应用程序供应商来完成大部分工作。通过让供应商支持触发器,它可以防止添加触发器无意中替换供应商提供的触发器的情况。
答案 4 :(得分:18)
不幸的是,我认为在SQL2000中没有一种干净的方法可以做到这一点。如果您将要求缩小到SQL Server 2005(及更高版本),那么您就可以开展业务了。您可以使用SQLDependency
中的System.Data.SqlClient
课程。请参阅Query Notifications in SQL Server (ADO.NET)。
答案 5 :(得分:17)
具有以给定间隔运行的DTS作业(或由Windows服务启动的作业)。每次运行时,它都会使用系统INFORMATION_SCHEMA表获取有关给定表的信息,并将此数据记录在数据存储库中。将返回的有关表结构的数据与上一次返回的数据进行比较。如果它不同,那么你知道结构已经改变了。
返回有关表ABC中所有列的信息的示例查询(理想情况下只列出您想要的INFORMATION_SCHEMA表中的列,而不是像我这样使用* select **):
select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'
您将监视不同的列和INFORMATION_SCHEMA视图,具体取决于您对“表的更改”的准确定义。
答案 6 :(得分:13)
疯狂猜测:如果你不想修改第三方的表,你能创建一个视图,然后在该视图上设置一个触发器吗?
答案 7 :(得分:6)
检查上次提交日期。每个数据库都有每个提交时间的历史记录。我相信它是ACID合规的标准。