我正在使用CONTEXT_INFO将用户名传递给删除触发器,以用于审计/历史记录表。我正在尝试理解CONTEXT_INFO的范围以及我是否正在创造潜在的竞争条件。
我的每个数据库表都有一个存储过程来处理删除。 delete stored proc将userId作为参数,并将CONTEXT_INFO设置为userId。我的删除触发器然后抓取CONTEXT_INFO并使用它来更新指示谁删除了行的审计表。
问题是,如果两个删除来自不同用户的sprocs同时执行,其中一个sprocs中设置的CONTEXT_INFO是否会由另一个sprocs触发的触发器消耗?
我已经看过这篇文章http://msdn.microsoft.com/en-us/library/ms189252.aspx,但我不清楚SQL Server中会话和批处理的范围,这对本文有用是关键!
我会发布代码,但此刻时间不够。如果不够清楚我会稍后编辑。
提前感谢您的帮助。
答案 0 :(得分:30)
上下文信息没有范围(在语言变量范围的意义上)并且与会话生存期绑定。设置后,上下文信息将保持在设置的值,直到连接关闭(会话终止)或设置为新值。由于会话上的执行总是顺序,因此不存在并发问题。
如果在过程中设置上下文信息,则随后在该会话上执行的任何触发器都将看到新设置的上下文信息值。正如您所建议的那样在上下文信息中设置用户ID值,并在触发器中使用它是上下文信息使用的典型示例,并且在并发性方面非常安全,因为基本上没有并发性可言。如果您计划在存储过程中设置上下文信息,然后在由于上述过程中发生的删除而运行的触发器中依赖它,那么您的批处理尚未完成,因此,根据您链接的文章,您检索来自sys.dm_exec_requests
DMV或CONTEXT_INFO()
函数的conetxt信息。它不会被推入sys.dm_exec_sessions
,这只能在您退出存储过程并完成发送到服务器的T-SQL批处理中的任何其他调用('request')之后才会被发送。
答案 1 :(得分:6)
我已经在一个客户端网站上使用了这种确切的方法进行审核,并且他们已经大量使用它近6个月了,没有任何问题。
上下文信息的范围限定为当前批次的当前连接以及当前批次完成后开始的所有批次。您环境中的两个用户要么不在同一个连接上,要么如果有连接共享,如果它们完全重叠,它们仍然会有自己的值。如果一个人跟在另一个之后,那么第二个人将覆盖第一个,但是无论如何它都会用它完成。至少这是我对其工作原理的理解。您可以查找MARS(多个活动结果集)以获取更多信息。