我一直在寻找有关SQL Server触发器隔离级别(或并发性或范围...我不确定应该如何精确地称呼它)的权威文档。
我找到了以下来源,这些来源表明我所相信的是正确的(也就是说,两个用户执行对同一张表的更新 - 即使是相同的行 - 那么独立和隔离的触发器将被执行):
我一直在寻找有关SQL Server触发器隔离级别(或并发性或范围...我不确定应该如何精确地称呼它)的权威文档。
我找到了以下来源,这些来源表明我所相信的是正确的(也就是说,两个用户执行对同一张表的更新 - 即使是相同的行 - 那么独立和隔离的触发器将被执行):
好的,隔离级别和作用域是两个非常不同的概念。
隔离级别
触发器在事务中运行。默认情况下,该事务应该使用READ COMMITTED
的默认隔离级别。然而,如果调用进程指定了不同的隔离级别,则会覆盖默认值。通常情况下,如果需要,在触发器本身中可以覆盖默认隔离级别。
根据MSDN页面的DML Triggers:
触发器和触发它的语句被视为单个事务,可以从触发器内部回滚。如果检测到严重错误(例如,磁盘空间不足),整个事务将自动回滚。
作用域
提供的上下文是:
{来自你}
两个用户,执行更新到同一个表--甚至是相同的行
{来自问题中第一个链接的MSDN文章,这篇文章“基本上是我正在尝试找到答案的同一个问题”}
插入和删除的表是否作用域限制于当前会话?换句话说,它们只包含当前范围内插入和删除的记录,还是它们包含同一表的所有当前更新操作的记录?甚至能够真正并发执行操作吗,或者锁定将防止此类操作?
在进入inserted
和deleted
表之前,应该非常清楚,在任何给定时刻,特定行上只会发生单个DML操作。两个或多个请求可能在完全相同的纳秒内到达,但所有请求都会轮流进行,一个接一个(是的,由于锁定)。
inserted
和deleted
表中的内容:是的,只有该特定事件的行才会在这两个伪表中(甚至可以)。如果执行将修改5行的UPDATE操作,则只有这5行会出现在inserted
和deleted
表中。而且,由于您正在寻找文档,MSDN页面使用inserted和deleted表指出:
deleted表存储DELETE和UPDATE语句期间受影响的行的副本。在执行DELETE或UPDATE语句期间,从触发器表中删除行并将其转移到deleted表中。deleted表和触发器表通常没有共同的行。
inserted表存储INSERT和UPDATE语句期间受影响的行的副本。在插入或更新事务期间,新行被添加到inserted表和触发器表中。inserted表中的行是触发器表中新行的副本。
将此与问题的其他部分联系起来,即涉及到Transaction Isolation Level的部分:Transaction Isolation Level对inserted
和deleted
表没有任何影响,因为它们专门针对该事件/查询。但是,该操作的净影响(在这两个伪表中捕获)仍然可以在其他进程使用READ UNCOMMITTED
隔离级别或NOLOCK
表提示时看到。为了澄清一些事情,上面链接的MSDN页面关于 inserted 和
deleted 表在开头就声明它们是“内存中”的,但这并不完全正确。从SQL Server 2005开始,这两个伪表实际上基于
tempdb 。 MSDN页面针对tempdb数据库指出:
tempdb 系统数据库是一种全局资源,可供连接到SQL Server实例的所有用户使用,并用于保存以下内容:
-
...
-
由数据修改事务生成的行版本,用于功能,例如:在线索引操作,多活动结果集(MARS)和AFTER触发器。
在SQL Server 2005之前, inserted 和 deleted 表是从事务日志中读取的(我认为)。
总之, inserted 和 deleted 表:
- 在Transaction中操作
- 是静态的(即只读)表
- 仅对当前Trigger可见
- 仅包含触发该Trigger实例的特定事件/操作/查询的行