原子事务

BizTalk 业务流程可设计为按照事务的传统“ACID”概念,执行不同部分的工作。 在执行时,这些离散的或原子的工作单位会将业务流程从一个一致的状态转移到独立于其他工作单位的一致且持久的新状态。 这通常通过使用 Scope 构造来完成,该构造使用事务语义封装工作单元。 也可以将整个业务流程定义为一个原子事务,而不使用作用域。 但是,这些作用域不能标记为事务性的,除非业务流程本身标记为长期或原子事务类型。 原子事务保证在事务性更新期间发生故障时可自动回滚任何部分更新,并且消除事务的影响(事务中进行的任何 .NET 调用的影响除外)。 BizTalk 业务流程中的原子事务与分布式事务处理协调器 (DTC) 事务大体相似,只是前者通常存活时间较短并且具有四个“ACID”属性(原子性、一致性、隔离性和持久性):

  • 原子性

    一个事务就表示一个原子的工作单位。 要么在事务内执行所有修改,要么不执行任何修改。

  • 一致性

    在提交时,事务必须在系统内保持数据的整体性。 如果某一事务在该事务开始前对已在内部保持了一致的数据库执行数据修改,则在提交该事务时,数据库仍必须在内部保持一致。 确保此属性的工作主要由应用程序开发人员负责。

  • 隔离

    并行事务进行的修改必须与其他并行事务进行的修改隔离。 并行运行的隔离事务所执行的修改将保持内部数据库一致性,与顺序运行事务完全一样。

  • 持续性

    在提交某一事务后,默认情况下所有修改都永久存在于系统中。 即使系统发生故障,这些修改也存在。

    在 BizTalk 业务流程中使用的原子事务支持以下隔离级别:

  • 读取已提交的内容

    在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。

  • 可重复的读取

    在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。 这防止了不可重复的读取,但仍有可能产生幻像行。

  • 可序列化

    放置一个范围锁,防止在事务完成前其他用户更新行或将行插入数据库中。

    BizTalk Server 确保原子事务内的状态变化(例如对变量、消息和对象的修改)只在事务提交后在原子事务的作用域外可见。 中间状态的变化将与业务流程的其他部分隔离开来。

注意

如果原子事务包含 接收 形状、 发送 形状或 启动业务流程 形状,则在提交事务之前不会执行相应的操作。

如果您要求对数据具有完全的 ACID 属性(例如,数据必须独立于其他事务),则必须只使用原子事务。

在原子事务失败时,所有状态都将重置,就像业务流程实例从来没有进入该作用域。 BizTalk 针对原子事务的规则是:所有变量(而不只是作用域的本地变量)都参与该事务。 在原子事务中使用的所有非序列化变量和消息都应声明为对作用域而言是本地的;否则,编译器将显示“变量…未标记为可序列化”错误。 所有原子作用域都将认为是“同步的”,并且如果实际上将同步的关键字用于原子作用域,则业务流程编译器将对冗余的使用发出警告。 共享数据的同步将从作用域开始一直扩展到作用域成功完成(包括在作用域结束时的状态持久化),或者扩展到异常处理程序完成时(如果出现错误)。 同步域并不扩展到补偿处理程序。

原子事务可与超时值(此时,业务流程将停止事务并且实例将挂起)相关联。 如果某一原子事务包含接收形状、发送形状或启动业务流程形状,则相应操作将不会在提交该事务前发生。

当用户故意引发 RetryTransactionException 或者如果在原子事务尝试提交时引发 PersistenceException ,则原子事务会重试。 例如,如果原子事务是分布式 DTC 事务的一部分,而该事务中的其他参与者停止了该事务,则可能会引发 PersistenceException。 同样,如果在尝试提交事务时出现数据库连接问题,也会引发 PersistenceException 。 如果对于 Retry=True 的原子范围发生这种情况,则最多重试 21 次。 默认情况下,每次重试之间的延迟为 2 秒(但可以修改该默认值)。 在执行完全部 21 次重试后,如果该事务仍无法提交,则挂起整个业务流程实例。 该实例可以手动恢复,并且将从冲突的原子作用域的开始处使用新计数器重新开始。

注意

只有 RetryTransactionExceptionPersistenceException 才能导致原子范围重试。 原子范围中引发的任何其他异常都不能导致重试,即使 Retry 属性设置为 True 也是如此。 如果这是用于导致重试) 的异常,则可以在 RetryTransactionException (上使用公共属性覆盖每两个连续重试之间的 2 秒默认延迟。

原子范围对嵌套其他事务有限制,这些事务不能嵌套其他事务或包括 Catch - 异常 块。

DTC 事务

尽管原子事务在行为上类似 DTC 事务,但默认情况下,它们并不是显式的 DTC 事务。 您可以显式地使这些事务成为 DTC 事务,只要在该事务中使用的任何对象都是从 System.EnterpriseServices.ServicedComponents 派生的 COM+ 对象,并且隔离级别在事务组件之间达成一致。

注意

一个原子事务不能包含任何其他事务,也不能包含异常处理程序。

注意

一个原子事务不能包含匹配的发送和接收操作,即,请求-响应对或使用同一相关集的发送和接收。

不可序列化的对象

如果您想要在某一业务流程内使用非序列化对象,则必须只在原子事务内使用它。 只要业务流程由引擎保存,在原子事务外使用此类对象都可能会导致数据丢失。

注意

每个原子作用域都表示一个持久化点,这意味着业务流程的状态将在每个持久化点保存到数据库。 广泛使用原子作用域将增加业务流程中的延迟时间。 代替出于创建非序列化对象目的而使用原子作用域,您可以使用不要求原子作用域的静态方法调用,从而无需持久化点。

另请参阅

使用原子事务的方案
长时间运行的事务