分布式事务Distributed Transactions

事务是一组相关的任务,作为独立于其他任务的独立单元成功(提交)或失败(中止)。A transaction is a set of related tasks that either succeeds (commit) or fails (abort) as a unit, among other things. 分布式事务是影响若干资源的事务。A distributed transaction is a transaction that affects several resources. 要提交分布式事务,所有参与者都必须保证对数据的任何更改是永久的。For a distributed transaction to commit, all participants must guarantee that any change to data will be permanent. 即使发生系统崩溃或其他不可预见的事件,更改也必须是永久的。Changes must persist despite system crashes or other unforeseen events. 即使只有一个参与者无法保证这一点,整个事务也将失败,在事务范围内对数据的任何更改均将回滚。If even a single participant fails to make this guarantee, the entire transaction fails, and any changes to data within the scope of the transaction are rolled back.

备注

如果 DataReader 在事务处于活动状态时启动,此时若尝试提交或回滚事务,将会引发异常。An exception will be thrown if you attempt to commit or roll back a transaction if a DataReader is started while the transaction is active.

使用 System.TransactionsWorking with System.Transactions

在 .NET Framework 中,分布式事务通过 System.Transactions 命名空间中的 API 进行管理。In the .NET Framework, distributed transactions are managed through the API in the System.Transactions namespace. 如果涉及多个永久资源管理器,System.Transactions API 会将分布式事务处理委托给事务监视器,例如 Microsoft 分布式事务协调程序 (MS DTC)。The System.Transactions API will delegate distributed transaction handling to a transaction monitor such as the Microsoft Distributed Transaction Coordinator (MS DTC) when multiple persistent resource managers are involved. 有关详细信息,请参阅事务基础知识For more information, see Transaction Fundamentals.

ADO.NET 2.0 引入了对使用 EnlistTransaction 方法在分布式事务中进行登记的支持,该方法会登记 Transaction 实例中的连接。ADO.NET 2.0 introduced support for enlisting in a distributed transaction using the EnlistTransaction method, which enlists a connection in a Transaction instance. 在以前版本的 ADO.NET 中,分布式事务中的显式登记使用连接的 EnlistDistributedTransaction 方法执行,以登记 ITransaction 实例中的连接,为了向后兼容,也支持该方法。In previous versions of ADO.NET, explicit enlistment in distributed transactions was performed using the EnlistDistributedTransaction method of a connection to enlist a connection in a ITransaction instance, which is supported for backwards compatibility. 有关企业服务事务的详细信息,请参阅与企业服务和 COM + 事务的互操作性For more information on Enterprise Services transactions, see Interoperability with Enterprise Services and COM+ Transactions.

在针对 SQL Server 数据库将 System.Transactions 事务与用于 SQL Server 的 .NET Framework 提供程序结合使用时,将自动创建一个轻型 TransactionWhen using a System.Transactions transaction with the .NET Framework Provider for SQL Server against a SQL Server database, a lightweight Transaction will automatically be used. 该事务可以根据需要提升为完全分布式事务。The transaction can then be promoted to a full distributed transaction on an as-needed basis. 有关详细信息,请参阅System. 事务与 SQL Server 的集成For more information, see System.Transactions Integration with SQL Server.

备注

默认情况下,Oracle 数据库可以同时参与的分布式事务的最大数目设置为 10。The maximum number of distributed transactions that an Oracle database can participate in at one time is set to 10 by default. 第 10 个事务之后,连接到 Oracle 数据库时将会引发异常。After the 10th transaction when connected to an Oracle database, an exception is thrown. Oracle 不支持分布式事务内的 DDLOracle does not support DDL inside of a distributed transaction.

自动在分布式事务中登记Automatically Enlisting in a Distributed Transaction

自动登记是将 ADO.NET 连接与 System.Transactions 集成的默认(和首选)方法。Automatic enlistment is the default (and preferred) way of integrating ADO.NET connections with System.Transactions. 如果连接对象确定事务处于活动状态,用 System.Transaction 术语来说是指 Transaction.Current 不为 Null,则连接对象会自动在现有分布式事务中登记。A connection object will automatically enlist in an existing distributed transaction if it determines that a transaction is active, which, in System.Transaction terms, means that Transaction.Current is not null. 自动事务登记在连接打开时进行。Automatic transaction enlistment occurs when the connection is opened. 之后,即使在事务范围内执行命令,也不会进行自动事务登记。It will not happen after that even if a command is executed inside of a transaction scope. 可以在现有事务中禁用自动登记,方法是将 Enlist=false 指定为 SqlConnection.ConnectionString 的连接字符串参数,或将 OLE DB Services=-7 指定为 OleDbConnection.ConnectionString 的连接字符串参数。You can disable auto-enlistment in existing transactions by specifying Enlist=false as a connection string parameter for a SqlConnection.ConnectionString, or OLE DB Services=-7 as a connection string parameter for an OleDbConnection.ConnectionString. 有关 Oracle 和 ODBC 连接字符串参数的更多信息,请参见 OracleConnection.ConnectionStringOdbcConnection.ConnectionStringFor more information on Oracle and ODBC connection string parameters, see OracleConnection.ConnectionString and OdbcConnection.ConnectionString.

手动在分布式事务中登记Manually Enlisting in a Distributed Transaction

如果禁用了自动登记或者您需要登记在连接打开后启动的事务,则可以使用所用提供程序的 EnlistTransaction 对象的 DbConnection 方法,在现有分布式事务中登记。If auto-enlistment is disabled or you need to enlist a transaction that was started after the connection was opened, you can enlist in an existing distributed transaction using the EnlistTransaction method of the DbConnection object for the provider you are working with. 在现有分布式事务中登记可以确保当提交或回滚了事务时,也提交或回滚对数据源所做作的代码修改。Enlisting in an existing distributed transaction ensures that, if the transaction is committed or rolled back, modifications made by the code at the data source will be committed or rolled back as well.

在分布式事务中登记尤其适用于为业务对象建立池连接。Enlisting in distributed transactions is particularly applicable when pooling business objects. 如果业务对象使用打开的连接建立池连接,自动事务登记只有在该连接打开时才会进行。If a business object is pooled with an open connection, automatic transaction enlistment only occurs when that connection is opened. 如果使用池中的业务对象执行多个事务,则该对象的打开连接不自动登记在新启动的事务中。If multiple transactions are performed using the pooled business object, the open connection for that object will not automatically enlist in newly initiated transactions. 在这种情况下,可以对该连接禁用自动事务登记,并使用 EnlistTransaction 在事务中登记连接。In this case, you can disable automatic transaction enlistment for the connection and enlist the connection in transactions using EnlistTransaction.

EnlistTransaction采用类型Transaction的单个自变量,该参数是对现有事务的引用。EnlistTransaction takes a single argument of type Transaction that is a reference to the existing transaction. 在调用连接的 EnlistTransaction 方法之后,所有使用该连接在数据源上进行的修改均将加入事务中。After calling the connection's EnlistTransaction method, all modifications made at the data source using the connection are included in the transaction. 传递空值将取消该连接在当前分布式事务登记中的登记。Passing a null value unenlists the connection from its current distributed transaction enlistment. 注意,在调用 EnlistTransaction 之前连接必须打开。Note that the connection must be opened before calling EnlistTransaction.

备注

在某个事务中显式登记了连接之后,在该事务完成之前,连接将无法取消登记或在另一个事务中登记。Once a connection is explicitly enlisted on a transaction, it cannot be un-enlisted or enlisted in another transaction until the first transaction finishes.

注意

如果连接已使用连接的 EnlistTransaction 方法开始了某个事务,BeginTransaction 将引发异常。EnlistTransaction throws an exception if the connection has already begun a transaction using the connection's BeginTransaction method. 但是,如果事务是在数据源上开始的本地事务(例如使用 SqlCommand 显式执行 BEGIN TRANSACTION 语句),EnlistTransaction 将回滚该本地事务并根据请求在现有分布式事务中登记。However, if the transaction is a local transaction started at the data source (for example, executing the BEGIN TRANSACTION statement explicitly using a SqlCommand), EnlistTransaction will roll back the local transaction and enlist in the existing distributed transaction as requested. 你不会接收本地事务已回滚的通知,必须管理任何未使用 BeginTransaction 开始的本地事务。You will not receive notice that the local transaction was rolled back, and must manage any local transactions not started using BeginTransaction. 如果您将用于 SQL Server 的 .NET Framework 数据提供程序 (SqlClient) 与 SQL Server 结合使用,则尝试登记会引发异常。If you are using the .NET Framework Data Provider for SQL Server (SqlClient) with SQL Server, an attempt to enlist will throw an exception. 所有其他情况将无法发现。All other cases will go undetected.

SQL Server 中的可提升事务Promotable Transactions in SQL Server

SQL Server 支持可提升的事务,在此类事务中,本地轻型事务可以仅在需要时自动提升为分布式事务。SQL Server supports promotable transactions in which a local lightweight transaction can be automatically promoted to a distributed transaction only if it is required. 可提升的事务不会调用分布式事务增加的系统开销,除非需要增加的系统开销。A promotable transaction does not invoke the added overhead of a distributed transaction unless the added overhead is required. 有关详细信息和代码示例,请参阅System. 事务与 SQL Server 的集成For more information and a code sample, see System.Transactions Integration with SQL Server.

配置分布式事务Configuring Distributed Transactions

为了使用分布式事务,您可能需要在网络上启用 MS DTC。You may need to enable the MS DTC over the network in order to use distributed transactions. 如果已启用 Windows 防火墙,则必须允许 MS DTC 服务使用网络或打开 MS DTC 端口。If have the Windows Firewall enabled, you must allow the MS DTC service to use the network or open the MS DTC port.

请参阅See also