在数据库事务设计中经常会遇到的疑惑
分布式查询和分布式事务
SQL Server 数据库引擎允许创建与 OLE DB 数据源(称为链接服务器)的链接。链接到 OLE DB 数据源之后,可以:
在 Transact-SQL 语句中作为表引用 OLE DB 数据源中的行集。
将命令传递给 OLE DB 数据源,并包含结果行集,作为 Transact-SQL 语句中的表。
每个分布式查询都可以引用多个链接服务器,而且可以对每台链接服务器执行更新或读取操作。单个分布式查询可以对某些链接服务器执行读取操作,并且对其他链接服务器执行更新操作。通常情况下,每当可能在某个事务中更新多台链接服务器中的数据时,数据库引擎都要求相应的 OLE DB 访问接口支持分布式事务。因此,链接服务器上所支持的查询类型取决于 OLE DB 访问接口中对事务的支持级别。OLE DB 为事务管理定义了两个可选的接口:
ITransactionLocal 支持 OLE DB 数据源中的本地事务。
ITransactionJoin 允许访问接口联接包含其他资源管理器的分布式事务。
所有支持 ITransactionJoin 的访问接口也都支持 ITransactionLocal。
对于不支持 ITransactionLocal 的访问接口,只允许执行读取操作。
对于支持 ITransactionLocal 的访问接口,允许执行所有更新操作。
数据库引擎的控制实例会自动调用参与更新操作的每台链接服务器中的 ITransactionLocal 以启动本地事务。如果语句执行成功则提交事务,如果语句执行失败则回滚事务。
如果分布式查询是针对分布式分区视图的,或是在连接为显式事务或隐式事务时执行,则应用以下规则:
对于不支持 ITransactionJoin 的访问接口,只允许执行读取操作。不支持任何事务或只支持 ITransactionLocal 的访问接口不能参与更新操作。
如果 SET XACT_ABORT 设置为 ON,则对于支持 ITransactionJoin 的任何访问接口,允许执行所有的更新操作。数据库引擎的控制实例会自动调用参与更新操作的每台链接服务器中的 ITransactionJoin,以便在分布式事务中注册该服务器。然后当主控服务器指示提交事务或回滚事务时,Microsoft 分布式事务处理协调器 (MS DTC) 提交事务或回滚事务。
如果 SET XACT_ABORT 设置为 OFF,则链接服务器还必须支持嵌套事务,才能对其执行更新操作。当会话已经有一个现有事务时,如果访问接口支持调用 ITransactionLocal::StartTransaction,则支持嵌套事务。这样,SQL Server 可以回滚分布式查询中的单个语句,而不必回滚整个事务。
上述规则隐含了对不支持嵌套事务的提供程序的以下限制:只有当 XACT_ABORT 选项设置为 ON 时,才允许在分布式事务中执行更新操作。
SET XACT_ABORT 的用途
指定当 Transact-SQL 语句出现运行时错误时,SQL Server 是否自动回滚到当前事务。
当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。
当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
编译错误(如语法错误)不受 SET XACT_ABORT 的影响。
对于大多数 OLE DB 提供程序(包括 SQL Server),必须将隐式或显示事务中的数据修改语句中的 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是在提供程序支持嵌套事务时。有关详细信息,请参阅 分布式查询和分布式事务。
SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。
XACT_STATE 的使用说明
用于报告当前正在运行的请求的用户事务状态的标量函数。XACT_STATE 指示请求是否有活动的用户事务,以及是否能够提交该事务。
XACT_STATE 返回下列值。
返回值 含义
1 当前请求有活动的用户事务。请求可以执行任何操作,包括写入数据和提交事务。
0 当前请求没有活动的用户事务。
-1 当前请求具有活动的用户事务,但出现了致使事务被归类为无法提交的事务的错误。请求无法提交事务或回滚到保存点;它只能请求完全回滚事务。请求在回滚事务之前无法执行任何写操作。请求在回滚事务之前只能执行读操作。事务回滚之后,请求便可执行读写操作并可开始新的事务。
当批处理结束运行时,数据库引擎将自动回滚所有不可提交的活动事务。如果事务进入不可提交状态时未发送错误消息,则当批处理结束时,将向客户端应用程序发送一个错误消息。该消息指示检测到并回滚了一个不可提交的事务。有关无法提交的事务的详细信息,请参阅在 Transact-SQL 中使用 TRY...CATCH。
XACT_STATE 和 @@TRANCOUNT 函数都可用于检测当前请求是否具有活动的用户事务。@@TRANCOUNT 不能用于确定事务是否已分类为不可提交的事务。XACT_STATE 不能用于确定是否有嵌套事务。