消息流可视为包含以下构成部分:
流处理消息时的事件序列可视为:
请注意,该事件序列对于访问表和编写输出消息没有区别。虽然流通常被视为用于生成某类输出消息,但这与更新数据库表之间实际并无差别。两种情况下,系统中数据的状态会有所变化。
=====x=========x===x=======x=============x====x===== 1 2 3 4 5 6
该行表示时间推移中系统内的数据。在时间 1,消息到达,且取自输入队列。在时间 2、3、4 和 5,更新数据库表或写入队列。这些状态的变化通过 x 符号表示。在最后的时间 6,输出消息离开且系统停顿。在这些事件之间,数据状态没有变化,并通过 = 符号表示。
现在我们来考虑一下故障对系统产生的影响。如果发生故障(如,拔出代理所运行的机器上的插头),先于故障进行的表和队列的状态变化仍会执行,但应在故障之后发生的变化则根本不会执行。这种情况很可能是无法接受的(如,从我当前帐户到借款帐户的付款已从当前帐户表发生,但未添加到借款帐户表)。
=====x=========x===x=======x=============x====x===== 1 2 3 4 5 6
该行表示时间推移中系统内的额外数据。在时间 1,消息到达,且取自输入队列。在此之前,系统中没有额外数据,它通过 - 符号表示。在此之后,状态表示消息已从队列中获取,因此它可在需要时放回队列中。在时间 2、3、4 和 5,更新数据库表或写入队列。额外数据的状态再次发生变化,从而可在需要时撤销对表和队列的更改。在最后的时间 6,输出消息离开,系统停顿且系统中不再有额外数据。在这些事件之间,额外数据的状态没有变化,并通过 = 符号表示。如果在 1 和 6 的任何时间内发生故障,便会使用额外数据来复原系统数据的原始状态,因此实际上便是,尚未写入任何输出队列,尚未更改任何表,且输入消息也尚未从输入队列中获取。如果未发生故障,则在时间 6 更改将变为永久的更改;即,后继故障后的撤销操作不会撤销更改。
该操作方式称为协调事务方式。成功完成事务称为落实。未成功完成则称为回滚。(有关如何实现该操作的更多更完整的描述,请参阅部分 XYZ;注意这不是缺省的,且并非所有数据库或排队系统都支持它。)
操作的协调事务方式的主要特性是,无论在何处或何时发生故障,对与一个输入消息关联的多个队列和表的所有更改会全部执行或都不执行;这就是该方式的主要优势。但不适用于所有情况。有关其适用情况的两个简单示例为:
MAIN -----x=========x===x=======x=============x====x----- 1 2 4 5 8 9 1st AUX --------------x======x========x------ 3 6 7
上一行如上述示例一样表示主要事务。确切地说,事务是一个抽象术语,但它具体之处在于在需要时复原原始状态所需的额外数据。下面一行表示辅助事务。在时间 3,进行了对表(或队列)的更新。另一个更新在时间 6 执行。在时间 7,流决定所有需要在辅助事务下进行的更改完成并落实更改。
如果在时间 7 之前流发生故障,则系统状态将不发生变化,因为两个事务都会回滚。如果在时间 7 之后并在时间 9 之前发生故障,则会落实辅助事务(已落实)但会回滚主要事务。如果在时间 9 之前没有发生故障,则不存在故障且两个事务都落实。
未限制您只能使用单个辅助事务,且未限制您只能对事务进行落实操作。可对数据库表执行多项更新,并且可落实或回滚这些更新。然后您可对相同数据库表或不同表进行更多更改,随后可落实或回滚这些更改。
您所使用的每个数据库都有其自己的辅助事务;因此,如果流更新属于不同数据库实例的表(如,不同的数据源名称),则每个数据库会有一个辅助事务。 这些更新可能(事实是必须)单独进行落实或回滚。任何在操作完成(时间 9)时尚未落实或回滚的更新将会根据处理成败与否(如,异常是否到达输入节点)由代理自动进行落实或回滚。
请注意,某些数据库类型(如 AIX 上的 DB2)不允许协调和非协调事务位于同一数据库实例中。这些情况下,必须创建独立数据库实例。您应该为协调事务配置一个数据库实例,而为非协调事务配置另一个数据库实例。
辅助数据库事务通过使用 ESQL COMMIT 和 ROLLBACK 语句进行落实或回滚。主要事务之外的操作通过在所使用的单独数据库语句(如 INSERT 和 UPDATE 语句)上指定 UNCOORDINATEDO 来获取。
并非所有排队系统都具有上述数据库的功能。 如在 MQ 中,对于队列的每个独立非协调读或写操作都有暗含的落实操作。因此无法放入两条消息再决定同时落实或回滚它们。这是基础系统的局限性,WebSphere Message Broker 无法将其隐藏。COMMIT 和 ROLLBACK 语句因此仅在数据库上操作。
以上描述仅涉及流但未提及节点。 流分为节点的方式本质上与有关事务的讨论无关。任意多个节点都可对主要事务和任意多个辅助事务,不受限制地以任何节点认为合适的方式进行更新。您所执行的操作则有关,但您的执行方式则无关。而事实上,仅数据库上的操作情况如此,只因为其他数据源(VSAM 和队列)有更多的有限功能。