嗯,隔离级别和范围是两个截然不同的东西。
隔离级别
触发器在事务内运行。默认情况下,该事务应使用默认隔离级别READ COMMITTED
。但是,如果调用进程指定了不同的隔离级别,那么这将覆盖默认值。像往常一样:如果需要,您应该能够在触发器本身内覆盖它。
根据 MSDN 页面DML 触发器 https://msdn.microsoft.com/en-us/library/ms178110.aspx:
触发器和触发它的语句被视为单个事务,可以从触发器内回滚。如果检测到严重错误(例如磁盘空间不足),整个事务将自动回滚。
Scope
提供的上下文是:
{来自你}
两个用户,对同一个表执行更新——甚至是相同的行
{来自问题中第一篇链接的 MSDN 文章,“本质上是我试图找到答案的同一个问题”}
插入和删除的表的范围是否仅限于当前会话?换句话说,它们将仅包含当前范围内插入和删除的记录,还是包含针对同一表的所有当前更新操作的记录?是否可以存在真正的并发操作,或者锁会阻止这种情况发生吗?
在进入之前inserted
and deleted
应该非常清楚地表明,在任何给定时刻,特定行上只会发生单个 DML 操作。两个或多个请求可能会在完全相同的纳秒内到来,但所有请求都会轮流进行,一次一个(是的,由于锁定)。
现在,关于inserted
and deleted
表:是的,只有该特定事件的行(甚至canbe) 在这两个伪表中。如果执行将修改 5 行的 UPDATE,则只有这 5 行将位于inserted
and deleted
表。由于您正在寻找文档,MSDN 页面使用插入和删除的表 https://msdn.microsoft.com/en-us/library/ms191300.aspx states:
已删除表存储 DELETE 和 UPDATE 语句期间受影响行的副本。在执行 DELETE 或 UPDATE 语句期间,行将从触发器表中删除并传输到已删除表。已删除表和触发器表通常没有公共行。
插入的表存储 INSERT 和 UPDATE 语句期间受影响的行的副本。在插入或更新事务期间,新行将添加到插入表和触发器表中。插入表中的行是触发器表中新行的副本。
将其与问题的另一部分联系起来,即与事务隔离级别相关的部分:事务隔离级别对inserted
and deleted
表,因为它们专门与该事件/查询相关。然而,在这两个伪表中捕获的该操作的净效果仍然可以是visible到其他进程,如果它们正在使用READ UNCOMMITTED
隔离级别或NOLOCK
表提示。
只是为了澄清一些事情,上面链接的 MSDN 页面有关inserted
and deleted
表一开始就声明它们“在内存中”,但这并不完全正确。从 SQL Server 2005 开始,这两个伪表实际上基于tempdb
。 MSDN 页面临时数据库 https://msdn.microsoft.com/en-us/library/ms190768.aspx states:
The tempdb系统数据库是一种全局资源,可供连接到 SQL Server 实例的所有用户使用,并用于保存以下内容:
在 SQL Server 2005 之前,inserted
and deleted
表是从事务日志中读取的(我相信)。
总而言之,inserted
and deleted
tables:
- 在交易中操作
- 是静态(即只读)表
- 仅对当前触发器可见
- 仅包含触发该触发器实例的特定事件/操作/查询的行