Boh*_*s27 4 sql-server sql-clr
每当将行插入某个表时,我都想添加一个触发器。触发器将触发 CLR 存储过程,该过程将执行数据库工作以外的其他操作,例如将 JSON 字符串写入 txt 文件并更新不同类型数据库的系统日志。
我的双手被束缚在使用这项技术上。最初我们打算编写一个 Windows 服务,它会定期扫描表,然后在插入新记录时运行该程序。
我的问题是:
我可以将 DLL 托管在不同的服务器上,以便在那里运行,或者当我部署 CLR 存储过程 dll 时,它是否总是在 SQL Server 数据库实例中运行?
我问的原因是我们不希望此代码减慢数据库服务器的速度,这可能会通过在代码中执行这些其他任务来实现。
我可以在不同的服务器上托管 DLL 以便在那里运行吗?
这将如何运作?如果您想在远程服务器上运行代码,您仍然需要本地服务器上的代码才能进行远程调用。
虽然,您可以设置 Express Edition 的实例来托管 SQLCLR 代码(它需要是一个存储过程和/或函数而不是触发器),然后创建一个链接服务器到该 Express 实例,然后让本地表上的 T-SQL 触发器通过链接服务器执行 SQLCLR 存储过程和/或函数。这样,调用远程代码的本地代码就是纯T-SQL。您甚至不需要在本地实例上启用 CLR 集成。
我问的原因是我们不希望此代码减慢数据库服务器的速度,这可能会通过在代码中执行这些其他任务来实现。
无论您在触发器内部做什么工作,无论是 T-SQL 触发器还是 SQLCLR 触发器,都将阻止该 DML 语句的完成。使用 SQLCLR 并没有真正改变那里的任何东西。
触发器在以下方面的确切要求是什么:
做数据库工作以外的事情,例如将 JSON 字符串写入 txt 文件并更新不同类型数据库的系统日志。
那些步骤/动作是否需要被事务绑定,这样如果INSERT操作失败,txt文件不存在,日志条目也不存在?
找到一种异步执行此操作的方法将是理想的(正如Jonathan也提到的)。但是,进行 Web 服务调用会删除事务方面,因此您可能会获取实际不存在的行的文件和日志条目。
使用 NT 服务对 INSERT 操作的影响最小,除非您正在使用WITH (NOLOCK)
(您不应该这样做),否则它只会看到成功的 INSERT 操作的结果。但是,该服务已断开连接,并且将比 Trigger 模型有更多的延迟,您需要找到一种方法来跟踪哪些条目是“新的”(NT 服务将需要跟踪一个DATETIME
或可能使用一个ROWVERSION
值并与@@DBTS
每次进行比较)。如果你的表已经有一个DATETIME
或DATETIME2
列被设置时INSERT
,那么你就可以利用现有的列,否则你将需要添加DATETIME
/ DATETIME2
/ROWVERSION
柱子。或者,如果您有一个基于 IDENTITY 或 Sequence 的 PK,那么您可以使用该值而不是添加列,并且 NT 服务只需要跟踪最近使用的ID
. 你会在哪里存储这个值?文本文件?注册表?云端”?(只是在开玩笑最后一个 ;-)
另一方面,您可能可以使用 Service Broker 将这两个部分匹配在一起。当触发器触发时,它可以向 Service Broker 队列添加一条消息,包括INSERTED
表中的任何必要信息。这允许它是异步的。然后,在另一端,队列读取器可以使用 SQLCLR 存储过程作为“激活过程”来获取该信息并采取适当的操作(创建 JSON 文件、在其他系统上记录条目等)。
此模型可能不需要 Service Broker。您可以设置自己的队列表,将 T-SQL 触发器转储条目放入其中,然后创建从队列表读取并调用 SQLCLR 存储过程和/或函数的 SQL Server 代理作业异步(无论它们位于本地服务器上还是跨链接服务器),然后在成功处理记录后删除记录。