语言

启用多重活动结果集

多重活动结果集 (MARS) 是一项用于 SQL Server 的功能,可用来对单个连接执行多个批处理。 如果对 SQL Server 启用了 MARS,使用的每个命令对象都将向该连接添加一个会话。

注意

单个 MARS 会话打开一个供 MARS 使用的逻辑连接,然后为每个活动命令打开一个逻辑连接。

在连接字符串中启用和禁用 MARS

注意

以下连接字符串使用 SQL Server 附带的示例 AdventureWorks 数据库。 提供的连接字符串假定数据库安装在名为 MSSQL1 的服务器上。 根据环境需要修改连接字符串。

默认情况下,MARS 功能处于禁用状态。 可以通过将 "MultipleActiveResultSets=True" 关键字对添加到连接字符串来将其启用。 “True”是启用 MARS 的唯一有效值。 下面的示例演示如何连接到 SQL Server 的实例以及如何指定是否应启用 MARS。

Dim connectionString As String = "..." & _
    "MultipleActiveResultSets=True"
string connectionString = "..." +
    "MultipleActiveResultSets=True";

可以通过将 "MultipleActiveResultSets=False" 关键字对添加到连接字符串来禁用 MARS。 “False”是禁用 MARS 的唯一有效值。

使用 MARS 时的特殊注意事项

通常,现有应用程序无需修改即可使用启用 MARS 的连接。 但是,如果希望在应用程序中使用 MARS 功能,则应了解以下特殊注意事项。

语句交替

MARS 操作在服务器上同步执行。 允许 SELECT 语句和 BULK INSERT 语句交错出现。 但是,数据操作语言 (DML) 和数据定义语言 (DDL) 语句是以原子方式执行的。 当原子批处理正在执行时,任何尝试执行的语句都会被阻止。 服务器上的并发执行不是 MARS 功能。

如果在 MARS 连接下提交两批,其中一个包含 SELECT 语句,另一个包含 DML 语句,则 DML 可以在 SELECT 语句执行过程中开始执行。 但是,DML 语句必须执行完毕,SELECT 语句才能继续执行。 如果这两个语句都在同一事务下运行,则在 SELECT 语句开始执行后,DML 语句所做的任何更改对读取操作不可见。

SELECT 语句中的 WAITFOR 语句在等待时(即直到生成第一行之前)不会产生事务。 这意味着当 WAITFOR 语句处于等待状态时,其他任何批处理都不能在同一连接内执行。

MARS 会话缓存

当连接在启用 MARS 的情况下打开时,提供程序会创建一个逻辑会话,从而增加开销。 为了减少开销, SqlClient 每个连接最多缓存 10 个 MARS 会话。 限制不能由用户调整。 如果达到此限制,提供程序将创建一个新会话,且不会返回错误。 缓存及其会话不会跨连接共享。 使用后,会话将返回到缓存,除非缓存已满,在这种情况下,提供程序会将其关闭。 缓存会话不会过期;在释放连接时,提供程序会清理它们。 提供程序在应用程序需要会话时填充缓存。

线程安全性

MARS 操作不是线程安全的。

连接池

启用了 MARS 的连接像其他任何连接一样被汇聚。 如果应用程序打开两个连接,一个启用了 MARS,一个禁用了 MARS,则两个连接位于不同的池中。 有关详细信息,请参阅 SQL Server 连接池 (ADO.NET)。

SQL Server 批处理执行环境

打开连接时,将定义默认环境。 然后,将此环境复制到逻辑 MARS 会话中。

批处理执行环境包括以下组件:

  • 设置选项(例如,ANSI_NULLS、DATE_FORMAT、LANGUAGE、TEXTSIZE)

  • 安全性上下文(用户/应用程序角色)

  • 数据库上下文(当前数据库)

  • 执行状态变量(例如,@@ERROR、@@ROWCOUNT、@@FETCH_STATUS@@IDENTITY)

  • 顶级临时表

借助 MARS,将默认执行环境与连接关联起来。 在特定连接下开始执行的每个新批处理都将接收默认环境的一个副本。 每当在给定的批处理下执行代码时,对环境所做的所有更改都将限制在特定的批处理范围内。 执行完成后,执行设置将复制到默认环境中。 如果一个批处理发出多个要在同一事务下按顺序执行的命令,语义将与早期客户端或服务器中涉及的连接所显示出来的语义相同。

并行执行

MARS 并非旨在删除对应用程序中多个连接的所有要求。 如果应用程序需要对服务器执行真正的并发命令,则应使用多个连接。

例如,考虑以下情况。 创建了两个命令对象,一个用于处理结果集,另一个用于更新数据;他们通过 MARS 共享公共连接。 在此方案中,Transaction. Commit 在更新时会失败,直到第一个命令对象上的所有结果都被读取完毕,并生成以下异常:

消息:事务上下文正在被其他会话使用。

源:.NET SqlClient 数据提供程序

应为:(null)

收到:Microsoft.Data.SqlClient.SqlException

有三种用于处理此方案的选项:

  1. 在创建读取器后启动事务,这样它就不属于该事务。 然后,每次更新都将成为一个独立的事务。

  2. 关闭读取器后,提交所有工作。 这可能会产生大量更新。

  3. 不要使用 MARS;而是像在 MARS 之前那样为每个命令对象使用单独的连接。

检测 MARS 支持

应用程序可以通过读取 SqlConnection.ServerVersion 值来检查 MARS 支持。 SQL Server 2005 的主版本号为 9;SQL Server 2008 的主版本号为 10。

请参阅